├── .github └── funding.yml ├── .gitignore ├── CNAME ├── LICENSE ├── README.md ├── _config.yml ├── assets ├── engram-800px.png ├── engram-KLA.png ├── engram-ergo-squeezed-800px.png └── raw │ ├── ergo │ ├── engram-ergo-base-layer-flat-squeezed.xcf │ ├── engram-ergo-base-layer-flat.xcf │ ├── engram-ergo-base-layer.xcf │ ├── engram-ergo-shift-layer-letters-left.xcf │ ├── engram-ergo-shift-layer-letters-right.xcf │ ├── engram-ergo-shift-layer-letters.xcf │ ├── engram-ergo-squeezed.png │ └── engram-ergo-squeezed.xcf │ └── std │ ├── engram-flat-800px.xcf │ └── engram-no-letters-flat-800px.xcf ├── code ├── combine_scoring_matrices.py ├── engram_functions.py ├── engram_variables.py ├── load_bigram_frequencies.py ├── load_flow_matrices.py ├── load_interkey_speeds24x24.py ├── load_interkey_speeds32x32.py ├── load_original_interkey_speeds.py ├── load_strength_data.py ├── rank_layouts.py ├── test │ ├── remove_parameters_rescore.py │ ├── score_speed_of_layouts.py │ └── score_strength_of_layouts.py └── website-typing-test │ ├── README.md │ ├── generate_string.py │ ├── index.html │ ├── script.js │ └── styles.css ├── compare_layouts.ipynb ├── data ├── KeyboardLayoutAnalyzer_data.py ├── Time24x24.py ├── Time32x32.py ├── bigram_counts_PeterNorvig.png ├── bigram_frequencies.txt ├── bigrams-trigrams-frequencies.xlsx ├── bigrams.txt ├── computer_language_char_frequency.png ├── interkey-timings.xlsx ├── letter_counts_PeterNorvig.png └── onegrams.txt ├── engram_layout_v2.0.ipynb ├── install ├── README.md ├── ios │ ├── Engram.xkeyboard │ ├── README.md │ ├── engram1.webp │ ├── engram2.webp │ └── engram3.webp ├── linux │ └── x_keyboard_extension │ │ ├── Makefile │ │ ├── README.md │ │ ├── usr-share-X11-xkb-rules-evdev │ │ └── usr-share-X11-xkb-symbols-us ├── mac │ ├── karabiner │ │ ├── README.md │ │ ├── deno.jsonc │ │ ├── engram.json │ │ ├── engram.ts │ │ ├── import_map.json │ │ ├── index.ts │ │ └── karabiner.edn │ └── ukelele │ │ ├── Engram.bundle │ │ └── Contents │ │ │ ├── Info.plist │ │ │ ├── Resources │ │ │ ├── Engram – QWERTY ⌘.keylayout │ │ │ ├── Engram.keylayout │ │ │ └── en.lproj │ │ │ │ └── InfoPlist.strings │ │ │ └── version.plist │ │ └── README.md └── windows │ └── microsoft_keyboard_layout_creator │ ├── engram │ ├── README.md │ └── engram.klc │ └── engram_with_qwerty_hotkeys │ ├── README.md │ ├── engram2b │ ├── Engram v2B.klc │ ├── Engram2B.jpg │ ├── Engram2BShft.jpg │ ├── Engram2B_amd64.msi │ ├── Engram2B_i386.msi │ ├── Engram2B_ia64.msi │ ├── amd64 │ │ └── Engram2B.dll │ ├── i386 │ │ └── Engram2B.dll │ ├── ia64 │ │ └── Engram2B.dll │ ├── setup.exe │ └── wow64 │ │ └── Engram2B.dll │ └── engram2c │ ├── Engram v2C.klc │ ├── Engram2C.jpg │ ├── Engram2CShft.jpg │ ├── Engram2C_amd64.msi │ ├── Engram2C_i386.msi │ ├── Engram2C_ia64.msi │ ├── amd64 │ └── Engram2C.dll │ ├── i386 │ └── Engram2C.dll │ ├── ia64 │ └── Engram2C.dll │ ├── setup.exe │ └── wow64 │ └── Engram2C.dll └── output ├── Factors24x24.txt ├── Factors24x24_heatmap.png ├── Factors24x24_histogram.png ├── Factors32x32.txt ├── Factors32x32_heatmap.png ├── Factors32x32_histogram.png ├── Flow24x24_heatmap.png ├── Flow24x24_histogram.png ├── Flow32x32_heatmap.png ├── Flow32x32_histogram.png ├── Speed24x24_heatmap.png ├── Speed24x24_histogram.png ├── Speed32x32_heatmap.png ├── Strength24x24.txt ├── Strength24x24_heatmap.png ├── Strength24x24_histogram.png ├── Strength32x32.txt ├── Strength32x32_heatmap.png ├── Strength32x32_histogram.png └── onegram_frequencies.txt /.github/funding.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github:binarybottle # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom:matter.childmind.org # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #* 2 | .#* 3 | .ipynb_checkpoints/*-checkpoint.ipynb 4 | .DS_Store 5 | deno.lock 6 | .clj-kondo 7 | .lsp -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | engram.dev -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright 2021 Arno Klein 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /assets/engram-800px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/engram-800px.png -------------------------------------------------------------------------------- /assets/engram-KLA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/engram-KLA.png -------------------------------------------------------------------------------- /assets/engram-ergo-squeezed-800px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/engram-ergo-squeezed-800px.png -------------------------------------------------------------------------------- /assets/raw/ergo/engram-ergo-base-layer-flat-squeezed.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/ergo/engram-ergo-base-layer-flat-squeezed.xcf -------------------------------------------------------------------------------- /assets/raw/ergo/engram-ergo-base-layer-flat.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/ergo/engram-ergo-base-layer-flat.xcf -------------------------------------------------------------------------------- /assets/raw/ergo/engram-ergo-base-layer.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/ergo/engram-ergo-base-layer.xcf -------------------------------------------------------------------------------- /assets/raw/ergo/engram-ergo-shift-layer-letters-left.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/ergo/engram-ergo-shift-layer-letters-left.xcf -------------------------------------------------------------------------------- /assets/raw/ergo/engram-ergo-shift-layer-letters-right.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/ergo/engram-ergo-shift-layer-letters-right.xcf -------------------------------------------------------------------------------- /assets/raw/ergo/engram-ergo-shift-layer-letters.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/ergo/engram-ergo-shift-layer-letters.xcf -------------------------------------------------------------------------------- /assets/raw/ergo/engram-ergo-squeezed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/ergo/engram-ergo-squeezed.png -------------------------------------------------------------------------------- /assets/raw/ergo/engram-ergo-squeezed.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/ergo/engram-ergo-squeezed.xcf -------------------------------------------------------------------------------- /assets/raw/std/engram-flat-800px.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/std/engram-flat-800px.xcf -------------------------------------------------------------------------------- /assets/raw/std/engram-no-letters-flat-800px.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/assets/raw/std/engram-no-letters-flat-800px.xcf -------------------------------------------------------------------------------- /code/combine_scoring_matrices.py: -------------------------------------------------------------------------------- 1 | # 24 keys: 2 | Factors24x24 = Flow24x24 3 | if apply_strength: 4 | Factors24x24 = Strength24x24 * Factors24x24 5 | 6 | # Print: 7 | print_matrix_info(matrix_data=Factors24x24, matrix_label="Factors24x24", nkeys=24, nlines=30) 8 | heatmap(data=Factors24x24, title="Factors24x24", xlabel="Key 1", ylabel="Key 2", print_output=print_output) 9 | 10 | # 32 keys: 11 | Factors32x32 = Flow32x32 12 | if apply_strength: 13 | Factors32x32 = Strength32x32 * Factors32x32 14 | 15 | # Print: 16 | print_matrix_info(matrix_data=Factors32x32, matrix_label="Factors32x32", nkeys=32, nlines=30) 17 | heatmap(data=Factors32x32, title="Factors32x32", xlabel="Key 1", ylabel="Key 2", print_output=print_output) -------------------------------------------------------------------------------- /code/engram_functions.py: -------------------------------------------------------------------------------- 1 | # %load code/engram_functions.py 2 | # Import dependencies 3 | import xlrd 4 | import numpy as np 5 | from sympy.utilities.iterables import multiset_permutations 6 | import matplotlib 7 | import matplotlib.pyplot as plt 8 | import seaborn as sns 9 | 10 | 11 | def permute_optimize_keys(fixed_letters, fixed_letter_indices, open_letter_indices, 12 | all_letters, keys, data_matrix, bigrams, bigram_frequencies, 13 | min_score=0, verbose=False): 14 | """ 15 | Find all permutations of letters, optimize layout, and generate output. 16 | """ 17 | matrix_selected = select_keys(data_matrix, keys, verbose=False) 18 | 19 | unassigned_letters = [] 20 | for all_letter in all_letters: 21 | if all_letter not in fixed_letters: 22 | unassigned_letters.append(all_letter) 23 | if len(unassigned_letters) == len(open_letter_indices): 24 | break 25 | 26 | letter_permutations = permute_letters(unassigned_letters, verbose) 27 | if verbose: 28 | print("{0} permutations".format(len(letter_permutations))) 29 | top_permutation, top_score = optimize_layout(np.array([]), matrix_selected, bigrams, bigram_frequencies, 30 | letter_permutations, open_letter_indices, 31 | fixed_letters, fixed_letter_indices, min_score, verbose) 32 | 33 | return top_permutation, top_score, letter_permutations 34 | 35 | 36 | def permute_optimize(starting_permutation, letters, all_letters, all_keys, 37 | data_matrix, bigrams, bigram_frequencies, min_score=0, verbose=False): 38 | """ 39 | Find all permutations of letters, optimize layout, and generate output. 40 | """ 41 | matrix_selected = select_keys(data_matrix, all_keys, verbose=False) 42 | open_positions = [] 43 | fixed_positions = [] 44 | open_letters = [] 45 | fixed_letters = [] 46 | assigned_letters = [] 47 | for iletter, letter in enumerate(letters): 48 | if letter.strip() == "": 49 | open_positions.append(iletter) 50 | for all_letter in all_letters: 51 | if all_letter not in letters and all_letter not in assigned_letters: 52 | open_letters.append(all_letter) 53 | assigned_letters.append(all_letter) 54 | break 55 | else: 56 | fixed_positions.append(iletter) 57 | fixed_letters.append(letter) 58 | 59 | letter_permutations = permute_letters(open_letters, verbose) 60 | if verbose: 61 | print("{0} permutations".format(len(letter_permutations))) 62 | top_permutation, top_score = optimize_layout(starting_permutation, matrix_selected, bigrams, 63 | bigram_frequencies, letter_permutations, open_positions, 64 | fixed_letters, fixed_positions, min_score, verbose) 65 | 66 | return top_permutation, top_score 67 | 68 | 69 | def select_keys(data_matrix, keys, verbose=False): 70 | """ 71 | Select keys to quantify pairwise relationships. 72 | """ 73 | # Extract pairwise entries for the keys: 74 | nkeys = len(keys) 75 | Select = np.zeros((nkeys, nkeys)) 76 | u = 0 77 | for i in keys: 78 | u += 1 79 | v = 0 80 | for j in keys: 81 | v += 1 82 | Select[u-1,v-1] = data_matrix[i-1,j-1] 83 | 84 | # Normalize matrix with min-max scaling to a range with max 1: 85 | newMin = np.min(Select) / np.max(Select) 86 | newMax = 1.0 87 | Select = newMin + (Select - np.min(Select)) * (newMax - newMin) / (np.max(Select) - np.min(Select)) 88 | 89 | if verbose: 90 | # Heatmap of array 91 | heatmap(data=Select, title="Matrix heatmap", xlabel="Key 1", ylabel="Key 2", print_output=False); plt.show() 92 | 93 | return Select 94 | 95 | 96 | def permute_letters(letters, verbose=False): 97 | """ 98 | Find all permutations of a given set of letters (max: 8-10 letters). 99 | """ 100 | letter_permutations = [] 101 | for p in multiset_permutations(letters): 102 | letter_permutations.append(p) 103 | letter_permutations = np.array(letter_permutations) 104 | 105 | return letter_permutations 106 | 107 | 108 | def score_layout(data_matrix, letters, bigrams, bigram_frequencies, verbose=False): 109 | """ 110 | Compute the score for a given letter-key layout (NOTE normalization step). 111 | """ 112 | # Create a matrix of bigram frequencies: 113 | nletters = len(letters) 114 | F2 = np.zeros((nletters, nletters)) 115 | 116 | # Find the bigram frequency for each ordered pair of letters in the permutation: 117 | for i1 in range(nletters): 118 | for i2 in range(nletters): 119 | bigram = letters[i1] + letters[i2] 120 | i2gram = np.where(bigrams == bigram) 121 | if np.size(i2gram) > 0: 122 | F2[i1, i2] = bigram_frequencies[i2gram][0] 123 | 124 | # Normalize matrices with min-max scaling to a range with max 1: 125 | newMax = 1 126 | minF2 = np.min(F2) 127 | maxF2 = np.max(F2) 128 | newMin2 = minF2 / maxF2 129 | F2 = newMin + (F2 - minF2) * (newMax - newMin2) / (maxF2 - minF2) 130 | 131 | # Compute the score for this permutation: 132 | score = np.average(data_matrix * F2) 133 | if verbose: 134 | print("Score for letter permutation {0}: {1}".format(letters, score)) 135 | 136 | return score 137 | 138 | 139 | def tally_bigrams(input_text, bigrams, normalize=True, verbose=False): 140 | """ 141 | Compute the score for a given letter-key layout (NOTE normalization step). 142 | """ 143 | # Find the bigram frequency for each ordered pair of letters in the input text 144 | #input_text = [str.upper(str(x)) for x in input_text] 145 | input_text = [str.upper(x) for x in input_text] 146 | nchars = len(input_text) 147 | F = np.zeros(len(bigrams)) 148 | 149 | for ichar in range(0, nchars-1): 150 | bigram = input_text[ichar] + input_text[ichar + 1] 151 | i2gram = np.where(bigrams == bigram) 152 | if np.size(i2gram) > 0: 153 | F[i2gram] += 1 154 | 155 | # Normalize matrix with min-max scaling to a range with max 1: 156 | if normalize: 157 | newMax = 1 158 | newMin = np.min(F) / np.max(F) 159 | F = newMin + (F - np.min(F)) * (newMax - newMin) / (np.max(F) - np.min(F)) 160 | 161 | bigram_frequencies_for_input = F 162 | 163 | if verbose: 164 | print("Bigram frequencies for input: {0}".format(bigram_frequencies_for_input)) 165 | 166 | return bigram_frequencies_for_input 167 | 168 | 169 | def tally_layout_samefinger_bigrams(layout, bigrams, bigram_frequencies, nkeys=32, verbose=False): 170 | """ 171 | Tally the number of same-finger bigrams within (a list of 24 letters representing) a layout: 172 | ['P','Y','O','U','C','I','E','A','G','K','J','X','M','D','L','B','R','T','N','S','H','V','W','F'] 173 | """ 174 | if nkeys == 32: 175 | # Left: Right: 176 | # 1 2 3 4 25 28 13 14 15 16 31 177 | # 5 6 7 8 26 29 17 18 19 20 32 178 | # 9 10 11 12 27 30 21 22 23 24 179 | same_finger_keys = [[1,5],[5,9],[1,9], [2,6],[6,10],[2,10], 180 | [3,7],[7,11],[3,11], [4,8],[8,12],[4,12], 181 | [25,26],[26,27],[25,27], [28,29],[29,30],[28,30], [31,32], 182 | [4,25],[4,26],[4,27], [8,25],[8,26],[8,27], [12,25],[12,26],[12,27], 183 | [13,28],[13,29],[13,30], [17,28],[17,29],[17,30], [21,28],[21,29],[21,30], 184 | [31,16],[31,20],[31,24], [32,16],[32,20],[32,24], 185 | [13,17],[17,21],[13,21], [14,18],[18,22],[14,22], 186 | [15,19],[19,23],[15,23], [16,20],[20,24],[16,24]] 187 | elif nkeys == 24: 188 | # 1 2 3 4 13 14 15 16 189 | # 5 6 7 8 17 18 19 20 190 | # 9 10 11 12 21 22 23 24 191 | same_finger_keys = [[1,5],[5,9],[1,9], [2,6],[6,10],[2,10], 192 | [3,7],[7,11],[3,11], [4,8],[8,12],[4,12], 193 | [13,17],[17,21],[13,21], [14,18],[18,22],[14,22], 194 | [15,19],[19,23],[15,23], [16,20],[20,24],[16,24]] 195 | 196 | layout = [str.upper(x) for x in layout] 197 | max_frequency = 1.00273E+11 198 | 199 | samefinger_bigrams = [] 200 | samefinger_bigram_counts = [] 201 | for bigram_keys in same_finger_keys: 202 | bigram1 = layout[bigram_keys[0]-1] + layout[bigram_keys[1]-1] 203 | bigram2 = layout[bigram_keys[1]-1] + layout[bigram_keys[0]-1] 204 | i2gram1 = np.where(bigrams == bigram1) 205 | i2gram2 = np.where(bigrams == bigram2) 206 | if np.size(i2gram1) > 0: 207 | samefinger_bigrams.append(bigram1) 208 | samefinger_bigram_counts.append(max_frequency * bigram_frequencies[i2gram1] / np.max(bigram_frequencies)) 209 | if np.size(i2gram2) > 0: 210 | samefinger_bigrams.append(bigram2) 211 | samefinger_bigram_counts.append(max_frequency * bigram_frequencies[i2gram2] / np.max(bigram_frequencies)) 212 | 213 | samefinger_bigrams_total = np.sum([x[0] for x in samefinger_bigram_counts]) 214 | 215 | if verbose: 216 | print(" Total same-finger bigram frequencies: {0:15.0f}".format(samefinger_bigrams_total)) 217 | 218 | return samefinger_bigrams, samefinger_bigram_counts, samefinger_bigrams_total 219 | 220 | 221 | def tally_layout_bigram_rolls(layout, bigrams, bigram_frequencies, nkeys=32, verbose=False): 222 | """ 223 | Tally the number of bigrams that engage little-to-index finger inward rolls 224 | for (a list of 24 or 32 letters representing) a layout, 225 | within the four columns of one hand, or any column across two hands. 226 | layout = ['P','Y','O','U','C','I','E','A','G','K','J','X','L','D','B','V','N','T','R','S','H','M','W','F'] 227 | bigram_rolls, bigram_roll_counts, bigram_rolls_total = tally_layout_bigram_rolls(layout, bigrams, bigram_frequencies, nkeys=24, verbose=True) 228 | """ 229 | if nkeys == 32: 230 | # Left: Right: 231 | # 1 2 3 4 25 28 13 14 15 16 31 232 | # 5 6 7 8 26 29 17 18 19 20 32 233 | # 9 10 11 12 27 30 21 22 23 24 234 | 235 | roll_keys = [[1,2],[2,3],[3,4], [5,6],[6,7],[7,8], [9,10],[10,11],[11,12], 236 | [16,15],[15,14],[14,13], [20,19],[19,18],[18,17], [24,23],[23,22],[22,21], 237 | [1,3],[2,4],[1,4], [5,7],[6,8],[5,8], [9,11],[10,12],[9,12], 238 | [16,14],[15,13],[16,13], [20,18],[19,17],[20,17], [24,22],[23,21],[24,21], 239 | [1,6],[1,7],[1,8],[2,7],[2,8],[3,8], 240 | [5,2],[5,3],[5,4],[6,3],[6,4],[7,4], 241 | [5,10],[5,11],[5,12],[6,11],[6,12],[7,12], 242 | [9,6],[9,7],[9,8],[10,7],[10,8],[11,8], 243 | [16,19],[16,18],[16,17],[15,18],[15,17],[14,17], 244 | [20,15],[20,14],[20,13],[19,14],[19,13],[18,13], 245 | [20,23],[20,22],[20,21],[19,22],[19,21],[18,21], 246 | [24,19],[24,18],[24,17],[23,18],[23,17],[22,17], 247 | [1,10],[1,11],[1,12],[2,11],[2,12],[3,12], 248 | [9,2],[9,3],[9,4],[10,3],[10,4],[11,4], 249 | [16,23],[16,22],[16,21],[15,22],[15,21],[14,21], 250 | [24,15],[24,14],[24,13],[23,14],[23,13],[22,13]] 251 | for i in [1,2,3,4,5,6,7,8,9,10,11,12, 25,26,27]: 252 | for j in [13,14,15,16,17,18,19,20,21,22,23,24, 28,29,30,31,32]: 253 | roll_keys.append([i,j]) 254 | for i in [13,14,15,16,17,18,19,20,21,22,23,24, 28,29,30,31,32]: 255 | for j in [1,2,3,4,5,6,7,8,9,10,11,12, 25,26,27]: 256 | roll_keys.append([i,j]) 257 | 258 | elif nkeys == 24: 259 | # 1 2 3 4 13 14 15 16 260 | # 5 6 7 8 17 18 19 20 261 | # 9 10 11 12 21 22 23 24 262 | roll_keys = [[1,2],[2,3],[3,4], [5,6],[6,7],[7,8], [9,10],[10,11],[11,12], 263 | [16,15],[15,14],[14,13], [20,19],[19,18],[18,17], [24,23],[23,22],[22,21], 264 | [1,3],[2,4],[1,4], [5,7],[6,8],[5,8], [9,11],[10,12],[9,12], 265 | [16,14],[15,13],[16,13], [20,18],[19,17],[20,17], [24,22],[23,21],[24,21], 266 | [1,6],[1,7],[1,8],[2,7],[2,8],[3,8], [5,2],[5,3],[5,4],[6,3],[6,4],[7,4], 267 | [5,10],[5,11],[5,12],[6,11],[6,12],[7,12], [9,6],[9,7],[9,8],[10,7],[10,8],[11,8], 268 | [16,19],[16,18],[16,17],[15,18],[15,17],[14,17], [20,15],[20,14],[20,13],[19,14],[19,13],[18,13], 269 | [20,23],[20,22],[20,21],[19,22],[19,21],[18,21], [24,19],[24,18],[24,17],[23,18],[23,17],[22,17], 270 | [1,10],[1,11],[1,12],[2,11],[2,12],[3,12], [9,2],[9,3],[9,4],[10,3],[10,4],[11,4], 271 | [16,23],[16,22],[16,21],[15,22],[15,21],[14,21], [24,15],[24,14],[24,13],[23,14],[23,13],[22,13]] 272 | for i in range(0,12): 273 | for j in range(12,24): 274 | roll_keys.append([i,j]) 275 | for i in range(12,24): 276 | for j in range(0,12): 277 | roll_keys.append([i,j]) 278 | 279 | layout = [str.upper(x) for x in layout] 280 | max_frequency = 1.00273E+11 281 | 282 | bigram_rolls = [] 283 | bigram_roll_counts = [] 284 | for bigram_keys in roll_keys: 285 | bigram1 = layout[bigram_keys[0]-1] + layout[bigram_keys[1]-1] 286 | bigram2 = layout[bigram_keys[1]-1] + layout[bigram_keys[0]-1] 287 | i2gram1 = np.where(bigrams == bigram1) 288 | i2gram2 = np.where(bigrams == bigram2) 289 | if np.size(i2gram1) > 0: 290 | bigram_rolls.append(bigram1) 291 | bigram_roll_counts.append(max_frequency * bigram_frequencies[i2gram1] / np.max(bigram_frequencies)) 292 | if np.size(i2gram2) > 0: 293 | bigram_rolls.append(bigram2) 294 | bigram_roll_counts.append(max_frequency * bigram_frequencies[i2gram2] / np.max(bigram_frequencies)) 295 | 296 | bigram_rolls_total = np.sum([x[0] for x in bigram_roll_counts]) 297 | 298 | if verbose: 299 | print(" Total bigram inward roll frequencies: {0:15.0f}".format(bigram_rolls_total)) 300 | 301 | return bigram_rolls, bigram_roll_counts, bigram_rolls_total 302 | 303 | 304 | def optimize_layout(starting_permutation, data_matrix, bigrams, bigram_frequencies, letter_permutations, 305 | open_positions, fixed_letters, fixed_positions=[], min_score=0, verbose=False): 306 | """ 307 | Compute scores for all letter-key layouts. 308 | """ 309 | top_permutation = starting_permutation 310 | top_score = min_score 311 | use_score_function = False 312 | 313 | nletters = len(open_positions) + len(fixed_positions) 314 | F2 = np.zeros((nletters, nletters)) 315 | 316 | # Loop through the permutations of the selected letters: 317 | for p in letter_permutations: 318 | letters = np.array(['W' for x in range(nletters)]) # KEEP to initialize! 319 | for imove, open_position in enumerate(open_positions): 320 | letters[open_position] = p[imove] 321 | for ifixed, fixed_position in enumerate(fixed_positions): 322 | letters[fixed_position] = fixed_letters[ifixed] 323 | 324 | # Compute the score for this permutation: 325 | if use_score_function: 326 | score = score_layout(data_matrix, letters, bigrams, bigram_frequencies, verbose=False) 327 | else: 328 | # Find the bigram frequency for each ordered pair of letters in the permutation: 329 | for i1 in range(nletters): 330 | for i2 in range(nletters): 331 | bigram = letters[i1] + letters[i2] 332 | i2gram = np.where(bigrams == bigram) 333 | if np.size(i2gram) > 0: 334 | F2[i1, i2] = bigram_frequencies[i2gram][0] 335 | 336 | # Normalize matrices with min-max scaling to a range with max 1: 337 | newMax = 1 338 | minF2 = np.min(F2) 339 | maxF2 = np.max(F2) 340 | newMin2 = minF2 / maxF2 341 | F = newMin + (F2 - minF2) * (newMax - newMin2) / (maxF2 - minF2) 342 | 343 | # Compute the score for this permutation: 344 | score = np.average(data_matrix * F) 345 | 346 | if score > top_score: 347 | top_score = score 348 | top_permutation = letters 349 | 350 | if verbose: 351 | if top_score == min_score: 352 | print("top_score = min_score") 353 | print("{0:0.8f}".format(top_score)) 354 | print(*top_permutation) 355 | 356 | return top_permutation, top_score 357 | 358 | 359 | def exchange_letters(letters, fixed_letter_indices, all_letters, all_keys, data_matrix, 360 | bigrams, bigram_frequencies, verbose=True): 361 | """ 362 | Exchange letters, 8 keys at a time (8! = 40,320) selected twice in 14 different ways: 363 | 364 | Indices: 365 | 0 1 2 3 12 13 14 15 366 | 4 5 6 7 16 17 18 19 367 | 8 9 10 11 20 21 22 23 368 | 369 | 1. Top rows 370 | 0 1 2 3 12 13 14 15 371 | 2. Bottom rows 372 | 8 9 10 11 20 21 22 23 373 | 3. Top and bottom rows on the right side 374 | 12 13 14 15 375 | 20 21 22 23 376 | 4. Top and bottom rows on the left side 377 | 0 1 2 3 378 | 8 9 10 11 379 | 5. Top right and bottom left rows 380 | 12 13 14 15 381 | 8 9 10 11 382 | 6. Top left and bottom right rows 383 | 0 1 2 3 384 | 20 21 22 23 385 | 7. Center of the top and bottom rows on both sides 386 | 1 2 13 14 387 | 9 10 21 22 388 | 8. The eight corners 389 | 0 3 12 15 390 | 8 11 20 23 391 | 9. Left half of the top and bottom rows on both sides 392 | 0 1 12 13 393 | 8 9 20 21 394 | 10. Right half of the top and bottom rows on both sides 395 | 2 3 14 15 396 | 10 11 22 23 397 | 11. Left half of non-home rows on the left and right half of the same rows on the right 398 | 0 1 14 15 399 | 8 9 22 23 400 | 12. Right half of non-home rows on the left and left half of the same rows on the right 401 | 2 3 12 13 402 | 10 11 20 21 403 | 13. Top center and lower sides 404 | 1 2 13 14 405 | 8 11 20 23 406 | 14. Top sides and lower center 407 | 0 3 12 15 408 | 9 10 21 22 409 | 15. Repeat 1-14 410 | 411 | """ 412 | top_score = score_layout(data_matrix, letters, bigrams, bigram_frequencies, verbose=False) 413 | print('Initial score: {0}'.format(top_score)) 414 | print(*letters) 415 | top_permutation = letters 416 | 417 | lists_of_open_indices = [ 418 | [0,1,2,3,12,13,14,15], 419 | [8,9,10,11,20,21,22,23], 420 | [12,13,14,15,20,21,22,23], 421 | [0,1,2,3,8,9,10,11], 422 | [12,13,14,15,8,9,10,11], 423 | [0,1,2,3,20,21,22,23], 424 | [1,2,13,14,9,10,21,22], 425 | [0,3,12,15,8,11,20,23], 426 | [0,1,12,13,8,9,20,21], 427 | [2,3,14,15,10,11,22,23], 428 | [0,1,14,15,8,9,22,23], 429 | [2,3,12,13,10,11,20,21], 430 | [1,2,8,11,13,14,20,23], 431 | [0,3,9,10,12,15,21,22] 432 | ] 433 | lists_of_print_statements = [ 434 | '1. Top rows', 435 | '2. Bottom rows', 436 | '3. Top and bottom rows on the right side', 437 | '4. Top and bottom rows on the left side', 438 | '5. Top right and bottom left rows', 439 | '6. Top left and bottom right rows', 440 | '7. Center of the top and bottom rows on both sides', 441 | '8. The eight corners', 442 | '9. Left half of the top and bottom rows on both sides', 443 | '10. Right half of the top and bottom rows on both sides', 444 | '11. Left half of non-home rows on the left and right half of the same rows on the right', 445 | '12. Right half of non-home rows on the left and left half of the same rows on the right', 446 | '13. Top center and lower sides', 447 | '14. Top sides and lower center' 448 | ] 449 | 450 | for istep in [1,2]: 451 | if istep == 1: 452 | s = "Set 1: 14 letter exchanges: " 453 | elif istep == 2: 454 | s = "Set 2: 14 letter exchanges: " 455 | 456 | for ilist, open_indices in enumerate(lists_of_open_indices): 457 | print_statement = lists_of_print_statements[ilist] 458 | 459 | if verbose: 460 | print('{0} {1}'.format(s, print_statement)) 461 | 462 | starting_permutation = top_permutation.copy() 463 | for open_index in open_indices: 464 | if open_index not in fixed_letter_indices: 465 | top_permutation[open_index] = '' 466 | 467 | top_permutation, top_score = permute_optimize(starting_permutation, top_permutation, letters24, 468 | keys24, data_matrix, bigrams, bigram_frequencies, 469 | min_score=top_score, verbose=True) 470 | if verbose: 471 | print('') 472 | print(' -------- DONE --------') 473 | print('') 474 | 475 | return top_permutation, top_score 476 | 477 | 478 | def rank_within_epsilon(numbers, epsilon, factor=False, verbose=True): 479 | """ 480 | numbers = np.array([10,9,8,7,6]) 481 | epsilon = 1 482 | rank_within_epsilon(numbers, epsilon, factor=False, verbose=True) 483 | >>> array([1., 1., 2., 2., 3.]) 484 | numbers = np.array([0.798900824, 0.79899900824, 0.79900824]) 485 | epsilon = 0.9**8 - 0.9**9 486 | factor24 = ((24**2 - 1) + (1-epsilon)) / (24**2) # 0.999925266109375 487 | rank_within_epsilon(numbers, factor24, factor=True, verbose=True) 488 | >>> array([2., 1., 1.]) 489 | """ 490 | numbers = np.array(numbers) 491 | Isort = np.argsort(-numbers) 492 | numbers_sorted = numbers[Isort] 493 | count = 1 494 | ranks = np.zeros(np.size(numbers)) 495 | for i, num in enumerate(numbers_sorted): 496 | if ranks[i] == 0: 497 | if factor: 498 | lower_bound = num * epsilon 499 | else: 500 | lower_bound = num - epsilon 501 | bounded_nums1 = num >= numbers_sorted 502 | bounded_nums2 = numbers_sorted >= lower_bound 503 | bounded_nums = bounded_nums1 * bounded_nums2 504 | count += 1 505 | for ibounded, bounded_num in enumerate(bounded_nums): 506 | if bounded_num == True: 507 | ranks[ibounded] = count 508 | 509 | uranks = np.unique(ranks) 510 | nranks = np.size(uranks) 511 | new_ranks = ranks.copy() 512 | new_count = 0 513 | for rank in uranks: 514 | new_count += 1 515 | same_ranks = ranks == rank 516 | for isame, same_rank in enumerate(same_ranks): 517 | if same_rank == True: 518 | new_ranks[isame] = new_count 519 | 520 | #ranks_sorted = new_ranks[Isort] 521 | ranks_sorted = [np.int(x) for x in new_ranks] 522 | 523 | if verbose: 524 | for i, num in enumerate(numbers_sorted): 525 | print(" ({0}) {1}".format(np.int(ranks_sorted[i]), num)) 526 | 527 | return numbers_sorted, ranks_sorted, Isort 528 | 529 | 530 | def print_matrix_info(matrix_data, matrix_label, nkeys, nlines=10): 531 | """ 532 | Print matrix output. 533 | """ 534 | print("{0} min = {1}, max = {2}".format(matrix_label, np.min(matrix_data), np.max(matrix_data))) 535 | matrix_flat = matrix_data.flatten() 536 | argsort = np.argsort(matrix_flat) 537 | print("{0} key number pairs with minimum values:".format(matrix_label)) 538 | for x in argsort[0:nlines]: 539 | if x % nkeys == 0: 540 | min_row = np.int(np.ceil(x / nkeys)) + 1 541 | min_col = 1 542 | else: 543 | min_row = np.int(np.ceil(x / nkeys)) 544 | min_col = x - nkeys * (min_row-1) + 1 545 | print(" {0} -> {1} ({2})".format(min_row, min_col, matrix_flat[x])) 546 | print("{0} key number pairs with maximum values:".format(matrix_label)) 547 | max_sort = argsort[-nlines::] 548 | for x in max_sort[::-1]: 549 | if x % nkeys == 0: 550 | max_row = np.int(np.ceil(x / nkeys)) + 1 551 | max_col = 1 552 | else: 553 | max_row = np.int(np.ceil(x / nkeys)) 554 | max_col = x - nkeys * (max_row-1) + 1 555 | print(" {0} -> {1} ({2})".format(max_row, max_col, matrix_flat[x])) 556 | 557 | 558 | def heatmap(data, title="", xlabel="", ylabel="", x_axis_labels=[], y_axis_labels=[], print_output=True): 559 | """ 560 | Plot heatmap of matrix. 561 | """ 562 | # use heatmap function, set the color as viridis and 563 | # make each cell seperate using linewidth parameter 564 | plt.figure() 565 | sns_plot = sns.heatmap(data, xticklabels=x_axis_labels, yticklabels=y_axis_labels, linewidths=1, 566 | cmap="viridis", square=True, vmin=np.min(data), vmax=np.max(data)) 567 | plt.title(title) 568 | plt.xlabel(xlabel) 569 | plt.ylabel(ylabel) 570 | sns_plot.set_xticklabels(x_axis_labels) #, rotation=75) 571 | sns_plot.set_yticklabels(y_axis_labels) 572 | if print_output: 573 | sns_plot.figure.savefig("{0}_heatmap.png".format(title)) 574 | 575 | 576 | def histmap(data, title="", print_output=True): 577 | """ 578 | Plot histogram. 579 | """ 580 | sns.distplot(data) 581 | plt.title(title) 582 | if print_output: 583 | sns_plot.figure.savefig("{0}_histogram.png".format(title)) 584 | 585 | 586 | def print_layout24(layout): 587 | """ 588 | Print layout. 589 | """ 590 | print(' {0} {1}'.format(' '.join(layout[0:4]), 591 | ' '.join(layout[12:16]))) 592 | print(' {0} {1}'.format(' '.join(layout[4:8]), 593 | ' '.join(layout[16:20]))) 594 | print(' {0} {1}'.format(' '.join(layout[8:12]), 595 | ' '.join(layout[20:24]))) 596 | 597 | 598 | def print_layout24_instances(layout, letters24, instances24, bigrams, bigram_frequencies): 599 | """ 600 | Print billions of instances per letter (not Z or Q) in layout form. 601 | layout = ['P','Y','O','U','C','I','E','A','G','K','J','X','M','D','L','B','R','T','N','S','H','V','W','F'] 602 | print_layout24_instances(layout, letters24, instances24, bigrams, bigram_frequencies) 603 | """ 604 | layout_instances = [] 605 | layout_instances_strings = [] 606 | for letter in layout: 607 | index = letters24.index(letter) 608 | layout_instances.append(instances24[index]) 609 | layout_instances_strings.append('{0:3.0f}'.format(instances24[index]/instances_denominator)) 610 | 611 | print(' {0} {1}'.format(' '.join(layout_instances_strings[0:4]), 612 | ' '.join(layout_instances_strings[12:16]))) 613 | print(' {0} {1}'.format(' '.join(layout_instances_strings[4:8]), 614 | ' '.join(layout_instances_strings[16:20]))) 615 | print(' {0} {1}'.format(' '.join(layout_instances_strings[8:12]), 616 | ' '.join(layout_instances_strings[20:24]))) 617 | left_sum = np.sum(layout_instances[0:12]) 618 | right_sum = np.sum(layout_instances[12:24]) 619 | pL = '' 620 | pR = '' 621 | if left_sum > right_sum: 622 | pL = ' ({0:3.2f}%)'.format(100 * (left_sum - right_sum) / right_sum) 623 | elif right_sum > left_sum: 624 | pR = ' ({0:3.2f}%)'.format(100 * (right_sum - left_sum) / left_sum) 625 | 626 | print('\n left: {0}{1} right: {2}{3}'.format(left_sum, pL, right_sum, pR)) 627 | 628 | tally_layout_samefinger_bigrams(layout, bigrams, bigram_frequencies, nkeys=24, verbose=True) 629 | tally_layout_bigram_rolls(layout, bigrams, bigram_frequencies, nkeys=24, verbose=True) 630 | 631 | 632 | def print_bigram_frequency(input_pair, bigrams, bigram_frequencies): 633 | """ 634 | >>> print_bigram_frequency(['t','h'], bigrams, bigram_frequencies) 635 | """ 636 | # Find the bigram frequency 637 | input_text = [str.upper(str(x)) for x in input_pair] 638 | nchars = len(input_text) 639 | for ichar in range(0, nchars-1): 640 | bigram1 = input_text[ichar] + input_text[ichar + 1] 641 | bigram2 = input_text[ichar + 1] + input_text[ichar] 642 | i2gram1 = np.where(bigrams == bigram1) 643 | i2gram2 = np.where(bigrams == bigram2) 644 | if np.size(i2gram1) > 0: 645 | freq1 = bigram_frequencies[i2gram1[0][0]] 646 | print("{0}: {1:3.2f}".format(bigram1, freq1)) 647 | if np.size(i2gram2) > 0: 648 | freq2 = bigram_frequencies[i2gram2[0][0]] 649 | print("{0}: {1:3.2f}".format(bigram2, freq2)) 650 | -------------------------------------------------------------------------------- /code/engram_variables.py: -------------------------------------------------------------------------------- 1 | # %load code/engram_variables.py 2 | # Print .png figures and .txt text files 3 | print_output = False # True 4 | 5 | # Apply strength data 6 | apply_strength = True 7 | min_strength_factor = 0.9 8 | 9 | letters24 = ['E','T','A','O','I','N','S','R','H','L','D','C','U','M','F','P','G','W','Y','B','V','K','X','J'] 10 | keys24 = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24] 11 | instances24 = [4.45155E+11,3.30535E+11,2.86527E+11,2.72277E+11,2.69732E+11,2.57771E+11, 12 | 2.32083E+11,2.23768E+11,1.80075E+11,1.44999E+11,1.36018E+11,1.19156E+11, 13 | 97273082907,89506734085,85635440629,76112599849,66615316232,59712390260, 14 | 59331661972,52905544693,37532682260,19261229433,8369138754,5657910830] 15 | 16 | 17 | # Establish which layouts are within a small difference of the top-scoring layout 18 | # (the smallest difference between two penalties, 0.9^8 - 0.9^9, in one of 24^2 key pairs): 19 | delta = 0.9**8 - 0.9**9 20 | factor24 = ((24**2 - 1) + (1-delta)) / (24**2) 21 | factor32 = ((32**2 - 1) + (1-delta)) / (32**2) 22 | 23 | # Establish which layouts are within a small difference of each other when using the speed matrix. 24 | # We define an epsilon equal to 13.158 ms for a single bigram (of the 32^2 possible bigrams), 25 | # where 13.158 ms is one tenth of 131.58 ms, the fastest measured digraph tapping speed (30,000/228 = 131.58 ms) 26 | # recorded in the study: "Estimation of digraph costs for keyboard layout optimization", 27 | # A Iseri, Ma Eksioglu, International Journal of Industrial Ergonomics, 48, 127-138, 2015. 28 | #data_matrix_speed = Speed32x32 29 | #time_range = 243 # milliseconds 30 | #norm_range = np.max(data_matrix_speed) - np.min(data_matrix_speed) # 0.6535662299854439 31 | #ms_norm = norm_range / time_range # 0.0026895729629030614 32 | #epsilon = 131.58/10 * ms_norm / (32**2) 33 | epsilon = 0.00003549615849447514 -------------------------------------------------------------------------------- /code/load_bigram_frequencies.py: -------------------------------------------------------------------------------- 1 | load_original_ngram_files = False 2 | if load_original_ngram_files: 3 | ngrams_table = "data/bigrams-trigrams-frequencies.xlsx" 4 | wb = xlrd.open_workbook(ngrams_table) 5 | ngrams_sheet = wb.sheet_by_index(0) 6 | # 1-grams and frequencies 7 | onegrams = np.array(()) 8 | onegram_frequencies = np.array(()) 9 | i = 0 10 | start1 = 0 11 | stop1 = 0 12 | while stop1 == 0: 13 | if ngrams_sheet.cell_value(i, 0) == "2-gram": 14 | stop1 = 1 15 | elif ngrams_sheet.cell_value(i, 0) == "1-gram": 16 | start1 = 1 17 | elif start1 == 1: 18 | onegrams = np.append(onegrams, ngrams_sheet.cell_value(i, 0)) 19 | onegram_frequencies = np.append(onegram_frequencies, ngrams_sheet.cell_value(i, 1)) 20 | i += 1 21 | onegram_frequencies = onegram_frequencies / np.sum(onegram_frequencies) 22 | 23 | # 2-grams and frequencies 24 | bigrams = np.array(()) 25 | bigram_frequencies = np.array(()) 26 | i = 0 27 | start1 = 0 28 | stop1 = 0 29 | while stop1 == 0: 30 | if ngrams_sheet.cell_value(i, 0) == "3-gram": 31 | stop1 = 1 32 | elif ngrams_sheet.cell_value(i, 0) == "2-gram": 33 | start1 = 1 34 | elif start1 == 1: 35 | bigrams = np.append(bigrams, ngrams_sheet.cell_value(i, 0)) 36 | bigram_frequencies = np.append(bigram_frequencies, ngrams_sheet.cell_value(i, 1)) 37 | i += 1 38 | bigram_frequencies = bigram_frequencies / np.sum(bigram_frequencies) 39 | 40 | # Save: 41 | save_output = False 42 | if save_output: 43 | file = open("onegrams.txt", "w+") 44 | file.write(str(onegrams)) 45 | file.close() 46 | file = open("onegram_frequencies.txt", "w+") 47 | file.write(str(onegram_frequencies)) 48 | file.close() 49 | file = open("bigrams.txt", "w+") 50 | file.write(str(bigrams)) 51 | file.close() 52 | file = open("bigram_frequencies.txt", "w+") 53 | file.write(str(bigram_frequencies)) 54 | file.close() 55 | 56 | # Print: 57 | print(repr(onegrams)) 58 | print(repr(onegram_frequencies)) 59 | print(repr(bigrams)) 60 | print(repr(bigram_frequencies)) 61 | 62 | else: 63 | onegrams = np.array(['E', 'T', 'A', 'O', 'I', 'N', 'S', 'R', 'H', 'L', 'D', 'C', 'U', 64 | 'M', 'F', 'P', 'G', 'W', 'Y', 'B', 'V', 'K', 'X', 'J', 'Q', 'Z'], 65 | dtype='lower row roll-outs: 87 | roll_ins_skip_home = [[1,10],[1,11],[1,12],[2,11],[2,12],[3,12], [9,2],[9,3],[9,4],[10,3],[10,4],[11,4], 88 | [16,23],[16,22],[16,21],[15,22],[15,21],[14,21], [24,15],[24,14],[24,13],[23,14],[23,13],[22,13]] 89 | for x in roll_ins_skip_home: 90 | T[x[1]-1, x[0]-1] *= outward 91 | 92 | # 9. Avoid stretching shorter fingers up and longer fingers down. 93 | # 1 2 3 4 13 14 15 16 94 | # 5 6 7 8 17 18 19 20 95 | # 9 10 11 12 21 22 23 24 96 | if index_above < 1.0: 97 | for x in [4]: 98 | for y in [4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]: 99 | T[x-1, y-1] *= index_above 100 | T[y-1, x-1] *= index_above 101 | for x in [13]: 102 | for y in [1,2,3,4,5,6,7,8,9,10,11,12,13,17,18,19,20,21,22,23,24]: 103 | T[x-1, y-1] *= index_above 104 | T[y-1, x-1] *= index_above 105 | if inside_top < 1.0: 106 | for x in [4,13]: 107 | for j in range(0,24): 108 | T[x-1, j] *= inside_top 109 | T[j, x-1] *= inside_top 110 | if side_top < 1.0: 111 | for x in [1,4,13,16]: 112 | for j in range(0,24): 113 | T[x-1, j] *= side_top 114 | T[j, x-1] *= side_top 115 | if side_above_1away < 1.0: 116 | for x in [1]: 117 | for y in [6,10]: 118 | T[x-1, y-1] *= side_above_1away 119 | T[y-1, x-1] *= side_above_1away 120 | for x in [5]: 121 | for y in [10]: 122 | T[x-1, y-1] *= side_above_1away 123 | T[y-1, x-1] *= side_above_1away 124 | for x in [4]: 125 | for y in [7,11]: 126 | T[x-1, y-1] *= side_above_1away 127 | T[y-1, x-1] *= side_above_1away 128 | for x in [8]: 129 | for y in [11]: 130 | T[x-1, y-1] *= side_above_1away 131 | T[y-1, x-1] *= side_above_1away 132 | for x in [13]: 133 | for y in [18,22]: 134 | T[x-1, y-1] *= side_above_1away 135 | T[y-1, x-1] *= side_above_1away 136 | for x in [17]: 137 | for y in [22]: 138 | T[x-1, y-1] *= side_above_1away 139 | T[y-1, x-1] *= side_above_1away 140 | for x in [16]: 141 | for y in [19,23]: 142 | T[x-1, y-1] *= side_above_1away 143 | T[y-1, x-1] *= side_above_1away 144 | for x in [20]: 145 | for y in [23]: 146 | T[x-1, y-1] *= side_above_1away 147 | T[y-1, x-1] *= side_above_1away 148 | if side_above_2away < 1.0: 149 | for x in [1]: 150 | for y in [7,11]: 151 | T[x-1, y-1] *= side_above_2away 152 | T[y-1, x-1] *= side_above_2away 153 | for x in [5]: 154 | for y in [11]: 155 | T[x-1, y-1] *= side_above_2away 156 | T[y-1, x-1] *= side_above_2away 157 | for x in [4]: 158 | for y in [6,10]: 159 | T[x-1, y-1] *= side_above_2away 160 | T[y-1, x-1] *= side_above_2away 161 | for x in [8]: 162 | for y in [10]: 163 | T[x-1, y-1] *= side_above_2away 164 | T[y-1, x-1] *= side_above_2away 165 | for x in [13]: 166 | for y in [19,23]: 167 | T[x-1, y-1] *= side_above_2away 168 | T[y-1, x-1] *= side_above_2away 169 | for x in [17]: 170 | for y in [23]: 171 | T[x-1, y-1] *= side_above_2away 172 | T[y-1, x-1] *= side_above_2away 173 | for x in [16]: 174 | for y in [18,22]: 175 | T[x-1, y-1] *= side_above_2away 176 | T[y-1, x-1] *= side_above_2away 177 | for x in [20]: 178 | for y in [22]: 179 | T[x-1, y-1] *= side_above_2away 180 | T[y-1, x-1] *= side_above_2away 181 | if side_above_3away < 1.0: 182 | for x in [1]: 183 | for y in [8,12]: 184 | T[x-1, y-1] *= side_above_3away 185 | T[y-1, x-1] *= side_above_3away 186 | for x in [5]: 187 | for y in [12]: 188 | T[x-1, y-1] *= side_above_3away 189 | T[y-1, x-1] *= side_above_3away 190 | for x in [4]: 191 | for y in [5,9]: 192 | T[x-1, y-1] *= side_above_3away 193 | T[y-1, x-1] *= side_above_3away 194 | for x in [8]: 195 | for y in [9]: 196 | T[x-1, y-1] *= side_above_3away 197 | T[y-1, x-1] *= side_above_3away 198 | for x in [13]: 199 | for y in [20,24]: 200 | T[x-1, y-1] *= side_above_3away 201 | T[y-1, x-1] *= side_above_3away 202 | for x in [17]: 203 | for y in [24]: 204 | T[x-1, y-1] *= side_above_3away 205 | T[y-1, x-1] *= side_above_3away 206 | for x in [16]: 207 | for y in [17,21]: 208 | T[x-1, y-1] *= side_above_3away 209 | T[y-1, x-1] *= side_above_3away 210 | for x in [20]: 211 | for y in [21]: 212 | T[x-1, y-1] *= side_above_3away 213 | T[y-1, x-1] *= side_above_3away 214 | if shorter_above < 1.0: 215 | for x in [1]: 216 | for y in [6,7,8,10,11,12]: 217 | T[x-1, y-1] *= shorter_above 218 | T[y-1, x-1] *= shorter_above 219 | for x in [2]: 220 | for y in [7,11]: 221 | T[x-1, y-1] *= shorter_above 222 | T[y-1, x-1] *= shorter_above 223 | for x in [4]: 224 | for y in [6,7,10,11]: 225 | T[x-1, y-1] *= shorter_above 226 | T[y-1, x-1] *= shorter_above 227 | 228 | for x in [5]: 229 | for y in [10,11,12]: 230 | T[x-1, y-1] *= shorter_above 231 | T[y-1, x-1] *= shorter_above 232 | for x in [6]: 233 | for y in [11]: 234 | T[x-1, y-1] *= shorter_above 235 | T[y-1, x-1] *= shorter_above 236 | for x in [8]: 237 | for y in [10,11]: 238 | T[x-1, y-1] *= shorter_above 239 | T[y-1, x-1] *= shorter_above 240 | 241 | for x in [16]: 242 | for y in [17,18,19,21,22,23]: 243 | T[x-1, y-1] *= shorter_above 244 | T[y-1, x-1] *= shorter_above 245 | for x in [15]: 246 | for y in [18,22]: 247 | T[x-1, y-1] *= shorter_above 248 | T[y-1, x-1] *= shorter_above 249 | for x in [13]: 250 | for y in [18,19,22,23]: 251 | T[x-1, y-1] *= shorter_above 252 | T[y-1, x-1] *= shorter_above 253 | 254 | for x in [20]: 255 | for y in [21,22,23]: 256 | T[x-1, y-1] *= shorter_above 257 | T[y-1, x-1] *= shorter_above 258 | for x in [19]: 259 | for y in [22]: 260 | T[x-1, y-1] *= shorter_above 261 | T[y-1, x-1] *= shorter_above 262 | for x in [17]: 263 | for y in [22,23]: 264 | T[x-1, y-1] *= shorter_above 265 | T[y-1, x-1] *= shorter_above 266 | 267 | if ring_above_middle < 1.0: 268 | ring_above_middles = [[2,7],[6,11],[2,11], 269 | [15,18],[19,22],[15,22]] 270 | for x in ring_above_middles: 271 | T[x[0]-1, x[1]-1] *= ring_above_middle 272 | T[x[1]-1, x[0]-1] *= ring_above_middle 273 | 274 | if middle_above_ring < 1.0: 275 | middle_above_rings = [[6,3],[10,7],[10,3], 276 | [19,14],[23,18],[23,14]] 277 | for x in middle_above_rings: 278 | T[x[0]-1, x[1]-1] *= middle_above_ring 279 | T[x[1]-1, x[0]-1] *= middle_above_ring 280 | 281 | # 10. Avoid using the same finger. 282 | # 1 2 3 4 13 14 15 16 283 | # 5 6 7 8 17 18 19 20 284 | # 9 10 11 12 21 22 23 24 285 | if same_finger < 1.0: 286 | same_fingers = [[1,5],[5,9],[1,9], [2,6],[6,10],[2,10], [3,7],[7,11],[3,11], [4,8],[8,12],[4,12], 287 | [13,17],[17,21],[13,21], [14,18],[18,22],[14,22], [15,19],[19,23],[15,23], [16,20],[20,24],[16,24]] 288 | for x in same_fingers: 289 | T[x[0]-1, x[1]-1] *= same_finger 290 | T[x[1]-1, x[0]-1] *= same_finger 291 | 292 | # 11. Avoid the upper and lower rows. 293 | # 1 2 3 4 13 14 15 16 294 | # 5 6 7 8 17 18 19 20 295 | # 9 10 11 12 21 22 23 24 296 | if not_home_row < 1.0: 297 | not_home_row_keys = [1,2,3,4, 9,10,11,12, 13,14,15,16, 21,22,23,24] 298 | for x in not_home_row_keys: 299 | for j in range(0,23): 300 | T[x-1, j] *= not_home_row 301 | T[j, x-1] *= not_home_row 302 | 303 | # 12. Avoid skipping over the home row. 304 | # 1 2 3 4 13 14 15 16 305 | # 5 6 7 8 17 18 19 20 306 | # 9 10 11 12 21 22 23 24 307 | if skip_row_0away < 1.0: 308 | skip_top = [1, 2, 3, 4, 13,14,15,16] 309 | skip_bot = [9,10,11,12, 21,22,23,24] 310 | for ix, x in enumerate(skip_top): 311 | y = skip_bot[ix] 312 | T[x-1, y-1] *= skip_row_0away 313 | T[y-1, x-1] *= skip_row_0away 314 | if skip_row_1away < 1.0: 315 | skip_top = [1, 2, 2, 3, 3, 4, 13,14,14,15,15,16] 316 | skip_bot = [10,9,11,10,12,11, 22,21,23,22,24,23] 317 | for ix, x in enumerate(skip_top): 318 | y = skip_bot[ix] 319 | T[x-1, y-1] *= skip_row_1away 320 | T[y-1, x-1] *= skip_row_1away 321 | if skip_row_2away < 1.0: 322 | skip_top = [1, 2,3, 4, 13,14,15,16] 323 | skip_bot = [11,12,9,10, 23,24,21,22] 324 | for ix, x in enumerate(skip_top): 325 | y = skip_bot[ix] 326 | T[x-1, y-1] *= skip_row_2away 327 | T[y-1, x-1] *= skip_row_2away 328 | if skip_row_3away < 1.0: 329 | skip_top = [1, 4, 13,16] 330 | skip_bot = [12,9, 24,21] 331 | for ix, x in enumerate(skip_top): 332 | y = skip_bot[ix] 333 | T[x-1, y-1] *= skip_row_3away 334 | T[y-1, x-1] *= skip_row_3away 335 | 336 | Flow24x24 = T 337 | 338 | # Normalize matrix with min-max scaling to a range with maximum = 1: 339 | newMin = np.min(Flow24x24) / np.max(Flow24x24) 340 | newMax = 1.0 341 | Flow24x24 = newMin + (Flow24x24 - np.min(Flow24x24)) * (newMax - newMin) / (np.max(Flow24x24) - np.min(Flow24x24)) 342 | 343 | return Flow24x24 344 | 345 | Flow24x24 = create_24x24_flow_matrix(not_home_row, side_top, 346 | side_above_3away, side_above_2away, side_above_1away, middle_above_ring, ring_above_middle, outward, 347 | skip_row_3away, skip_row_2away, skip_row_1away, skip_row_0away, same_finger, lateral, same_hand, 348 | shorter_above, adjacent_offset, inside_top, index_above) 349 | 350 | # Print: 351 | print_matrix_info(matrix_data=Flow24x24, matrix_label="Flow24x24", nkeys=24, nlines=30) 352 | heatmap(data=Flow24x24, title="Flow24x24", xlabel="Key 1", ylabel="Key 2", print_output=print_output) 353 | 354 | 355 | def create_32x32_flow_matrix(not_home_row, side_top, side_above_3away, side_above_2away, side_above_1away, 356 | middle_above_ring, ring_above_middle, outward, skip_row_3away, 357 | skip_row_2away, skip_row_1away, skip_row_0away, same_finger, lateral, 358 | same_hand, shorter_above, adjacent_offset, inside_top, index_above): 359 | 360 | all_32_keys = [1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24, 361 | 25,26,27, 28,29,30, 31,32] 362 | 363 | # Create a matrix and multiply by flow factors that promote easy interkey transitions: 364 | T = np.ones((32, 32)) 365 | 366 | if lateral < 1.0: 367 | for x in all_32_keys: 368 | for y in [25,26,27, 28,29,30, 31,32]: 369 | T[x-1, y-1] *= lateral 370 | T[y-1, x-1] *= lateral 371 | 372 | # 7. Promote alternating between hands over uncomfortable transitions with the same hand. 373 | if same_hand < 1.0: 374 | for i in [1,2,3,4,5,6,7,8,9,10,11,12, 25,26,27]: 375 | for j in [1,2,3,4,5,6,7,8,9,10,11,12, 25,26,27]: 376 | T[i-1,j-1] *= same_hand 377 | for i in [13,14,15,16,17,18,19,20,21,22,23,24, 28,29,30,31,32]: 378 | for j in [13,14,15,16,17,18,19,20,21,22,23,24, 28,29,30,31,32]: 379 | T[i-1,j-1] *= same_hand 380 | 381 | # 8. Promote little-to-index-finger roll-ins over index-to-little-finger outsward rolls. 382 | # Penalize (index, little) finger lateral movements: 383 | # 1 2 3 4 25 28 13 14 15 16 31 384 | # 5 6 7 8 26 29 17 18 19 20 32 385 | # 9 10 11 12 27 30 21 22 23 24 386 | if outward < 1.0: 387 | 388 | # same-row roll-outs: 389 | roll_ins = [[1,2],[2,3],[3,4], [5,6],[6,7],[7,8], [9,10],[10,11],[11,12], 390 | [16,15],[15,14],[14,13], [20,19],[19,18],[18,17], [24,23],[23,22],[22,21]] 391 | for x in roll_ins: 392 | T[x[1]-1, x[0]-1] *= outward 393 | 394 | # same-row roll-outs, skipping keys: 395 | roll_ins_skip_keys = [[1,3],[2,4],[1,4], [5,7],[6,8],[5,8], [9,11],[10,12],[9,12], 396 | [16,14],[15,13],[16,13], [20,18],[19,17],[20,17], [24,22],[23,21],[24,21]] 397 | #[1,25],[2,25],[3,25], 398 | #[5,26],[6,26],[7,26], 399 | #[9,27],[10,27],[11,27], 400 | #[16,28],[15,28],[14,28], 401 | #[20,29],[19,29],[18,29], 402 | #[24,30],[23,30],[22,30], 403 | #[31,15],[31,14],[31,13],[31,28], 404 | #[32,19],[32,18],[32,17],[32,29]] 405 | for x in roll_ins_skip_keys: 406 | T[x[1]-1, x[0]-1] *= outward 407 | 408 | # adjacent-row roll-outs: 409 | # 1 2 3 4 25 28 13 14 15 16 31 410 | # 5 6 7 8 26 29 17 18 19 20 32 411 | # 9 10 11 12 27 30 21 22 23 24 412 | roll_ins_adj_rows = [[1,6],[1,7],[1,8],[2,7],[2,8],[3,8], 413 | [5,2],[5,3],[5,4],[6,3],[6,4],[7,4], 414 | [5,10],[5,11],[5,12],[6,11],[6,12],[7,12], 415 | [9,6],[9,7],[9,8],[10,7],[10,8],[11,8], 416 | [16,19],[16,18],[16,17],[15,18],[15,17],[14,17], 417 | [20,15],[20,14],[20,13],[19,14],[19,13],[18,13], 418 | [20,23],[20,22],[20,21],[19,22],[19,21],[18,21], 419 | [24,19],[24,18],[24,17],[23,18],[23,17],[22,17]] 420 | #[5,25],[6,25],[7,25],[8,25], 421 | #[5,27],[6,27],[7,27],[8,27], 422 | #[1,26],[2,26],[3,26],[4,26], 423 | #[9,26],[10,26],[11,26],[12,26], 424 | #[16,29],[15,29],[14,29],[13,29], 425 | #[24,29],[23,29],[22,29],[21,29], 426 | #[20,28],[19,28],[18,28],[17,28], 427 | #[20,30],[19,30],[18,30],[17,30], 428 | #[31,20],[31,19],[31,18],[31,17],[31,29], 429 | #[32,16],[32,15],[32,14],[32,13],[32,28], 430 | #[32,24],[32,23],[32,22],[32,21],[32,30]] 431 | for x in roll_ins_adj_rows: 432 | T[x[1]-1, x[0]-1] *= outward 433 | 434 | # upper<->lower row roll-outs: 435 | roll_ins_skip_home = [[1,10],[1,11],[1,12],[2,11],[2,12],[3,12], 436 | [9,2],[9,3],[9,4],[10,3],[10,4],[11,4], 437 | [16,23],[16,22],[16,21],[15,22],[15,21],[14,21], 438 | [24,15],[24,14],[24,13],[23,14],[23,13],[22,13]] 439 | #[16,30],[15,30],[14,30],[13,30], 440 | #[9,25],[10,25],[11,25],[12,25], 441 | #[24,28],[23,28],[22,28],[21,28], 442 | #[1,27],[2,27],[3,27],[4,27], 443 | #[31,24],[31,23],[31,22],[31,21],[31,30]] 444 | for x in roll_ins_skip_home: 445 | T[x[1]-1, x[0]-1] *= outward 446 | 447 | # 9. Avoid stretching shorter fingers up and longer fingers down. 448 | # 1 2 3 4 25 28 13 14 15 16 31 449 | # 5 6 7 8 26 29 17 18 19 20 32 450 | # 9 10 11 12 27 30 21 22 23 24 451 | if index_above < 1.0: 452 | for x in [4]: 453 | for y in [4,5,6,7,8,26,9,10,11,12,27,28,13,14,15,16,31,29,17,18,19,20,32,30,21,22,23,24]: 454 | T[x-1, y-1] *= index_above 455 | T[y-1, x-1] *= index_above 456 | for x in [25]: 457 | for y in [25,5,6,7,8,26,9,10,11,12,27,28,13,14,15,16,31,29,17,18,19,20,32,30,21,22,23,24]: 458 | T[x-1, y-1] *= index_above 459 | T[y-1, x-1] *= index_above 460 | for x in [13]: 461 | for y in [1,2,3,4,25,5,6,7,8,26,9,10,11,12,27,13,29,17,18,19,20,32,30,21,22,23,24]: 462 | T[x-1, y-1] *= index_above 463 | T[y-1, x-1] *= index_above 464 | for x in [28]: 465 | for y in [1,2,3,4,25,5,6,7,8,26,9,10,11,12,27,28,29,17,18,19,20,32,30,21,22,23,24]: 466 | T[x-1, y-1] *= index_above 467 | T[y-1, x-1] *= index_above 468 | if inside_top < 1.0: 469 | for x in [4,25,28,13]: 470 | for j in range(0,32): 471 | T[x-1, j] *= inside_top 472 | T[j, x-1] *= inside_top 473 | if side_top < 1.0: 474 | for x in [1,4,25,28,13,16,31]: 475 | for j in range(0,32): 476 | T[x-1, j] *= side_top 477 | T[j, x-1] *= side_top 478 | if side_above_1away < 1.0: 479 | for x in [1]: 480 | for y in [6,10]: 481 | T[x-1, y-1] *= side_above_1away 482 | T[y-1, x-1] *= side_above_1away 483 | for x in [5]: 484 | for y in [10]: 485 | T[x-1, y-1] *= side_above_1away 486 | T[y-1, x-1] *= side_above_1away 487 | for x in [4,25]: 488 | for y in [7,11]: 489 | T[x-1, y-1] *= side_above_1away 490 | T[y-1, x-1] *= side_above_1away 491 | for x in [8,26]: 492 | for y in [11]: 493 | T[x-1, y-1] *= side_above_1away 494 | T[y-1, x-1] *= side_above_1away 495 | for x in [13,28]: 496 | for y in [18,22]: 497 | T[x-1, y-1] *= side_above_1away 498 | T[y-1, x-1] *= side_above_1away 499 | for x in [17,29]: 500 | for y in [22]: 501 | T[x-1, y-1] *= side_above_1away 502 | T[y-1, x-1] *= side_above_1away 503 | for x in [16,31]: 504 | for y in [19,23]: 505 | T[x-1, y-1] *= side_above_1away 506 | T[y-1, x-1] *= side_above_1away 507 | for x in [20,32]: 508 | for y in [23]: 509 | T[x-1, y-1] *= side_above_1away 510 | T[y-1, x-1] *= side_above_1away 511 | if side_above_2away < 1.0: 512 | for x in [1]: 513 | for y in [7,11]: 514 | T[x-1, y-1] *= side_above_2away 515 | T[y-1, x-1] *= side_above_2away 516 | for x in [5]: 517 | for y in [11]: 518 | T[x-1, y-1] *= side_above_2away 519 | T[y-1, x-1] *= side_above_2away 520 | for x in [4,25]: 521 | for y in [6,10]: 522 | T[x-1, y-1] *= side_above_2away 523 | T[y-1, x-1] *= side_above_2away 524 | for x in [8,26]: 525 | for y in [10]: 526 | T[x-1, y-1] *= side_above_2away 527 | T[y-1, x-1] *= side_above_2away 528 | for x in [13,28]: 529 | for y in [19,23]: 530 | T[x-1, y-1] *= side_above_2away 531 | T[y-1, x-1] *= side_above_2away 532 | for x in [17,29]: 533 | for y in [23]: 534 | T[x-1, y-1] *= side_above_2away 535 | T[y-1, x-1] *= side_above_2away 536 | for x in [16,31]: 537 | for y in [18,22]: 538 | T[x-1, y-1] *= side_above_2away 539 | T[y-1, x-1] *= side_above_2away 540 | for x in [20,32]: 541 | for y in [22]: 542 | T[x-1, y-1] *= side_above_2away 543 | T[y-1, x-1] *= side_above_2away 544 | if side_above_3away < 1.0: 545 | for x in [1]: 546 | for y in [8,12,26,27]: 547 | T[x-1, y-1] *= side_above_3away 548 | T[y-1, x-1] *= side_above_3away 549 | for x in [5]: 550 | for y in [12,27]: 551 | T[x-1, y-1] *= side_above_3away 552 | T[y-1, x-1] *= side_above_3away 553 | for x in [4,25]: 554 | for y in [5,9]: 555 | T[x-1, y-1] *= side_above_3away 556 | T[y-1, x-1] *= side_above_3away 557 | for x in [8,26]: 558 | for y in [9]: 559 | T[x-1, y-1] *= side_above_3away 560 | T[y-1, x-1] *= side_above_3away 561 | for x in [13,28]: 562 | for y in [20,24,32]: 563 | T[x-1, y-1] *= side_above_3away 564 | T[y-1, x-1] *= side_above_3away 565 | for x in [17,29]: 566 | for y in [24]: 567 | T[x-1, y-1] *= side_above_3away 568 | T[y-1, x-1] *= side_above_3away 569 | for x in [16,31]: 570 | for y in [17,21,29,30]: 571 | T[x-1, y-1] *= side_above_3away 572 | T[y-1, x-1] *= side_above_3away 573 | for x in [20,32]: 574 | for y in [21,30]: 575 | T[x-1, y-1] *= side_above_3away 576 | T[y-1, x-1] *= side_above_3away 577 | 578 | 579 | # 1 2 3 4 25 28 13 14 15 16 31 580 | # 5 6 7 8 26 29 17 18 19 20 32 581 | # 9 10 11 12 27 30 21 22 23 24 582 | if shorter_above < 1.0: 583 | for x in [1]: 584 | for y in [6,7,8,26,10,11,12,27]: 585 | T[x-1, y-1] *= shorter_above 586 | T[y-1, x-1] *= shorter_above 587 | for x in [2]: 588 | for y in [7,11]: 589 | T[x-1, y-1] *= shorter_above 590 | T[y-1, x-1] *= shorter_above 591 | for x in [4]: 592 | for y in [6,7,10,11]: 593 | T[x-1, y-1] *= shorter_above 594 | T[y-1, x-1] *= shorter_above 595 | for x in [25]: 596 | for y in [6,7,10,11]: 597 | T[x-1, y-1] *= shorter_above 598 | T[y-1, x-1] *= shorter_above 599 | 600 | for x in [5]: 601 | for y in [10,11,12,27]: 602 | T[x-1, y-1] *= shorter_above 603 | T[y-1, x-1] *= shorter_above 604 | for x in [6]: 605 | for y in [11]: 606 | T[x-1, y-1] *= shorter_above 607 | T[y-1, x-1] *= shorter_above 608 | for x in [8]: 609 | for y in [10,11]: 610 | T[x-1, y-1] *= shorter_above 611 | T[y-1, x-1] *= shorter_above 612 | for x in [26]: 613 | for y in [10,11]: 614 | T[x-1, y-1] *= shorter_above 615 | T[y-1, x-1] *= shorter_above 616 | 617 | for x in [16]: 618 | for y in [29,17,18,19,30,21,22,23]: 619 | T[x-1, y-1] *= shorter_above 620 | T[y-1, x-1] *= shorter_above 621 | for x in [31]: 622 | for y in [29,17,18,19,30,21,22,23]: 623 | T[x-1, y-1] *= shorter_above 624 | T[y-1, x-1] *= shorter_above 625 | for x in [15]: 626 | for y in [18,22]: 627 | T[x-1, y-1] *= shorter_above 628 | T[y-1, x-1] *= shorter_above 629 | for x in [13]: 630 | for y in [18,19,22,23]: 631 | T[x-1, y-1] *= shorter_above 632 | T[y-1, x-1] *= shorter_above 633 | for x in [28]: 634 | for y in [18,19,22,23]: 635 | T[x-1, y-1] *= shorter_above 636 | T[y-1, x-1] *= shorter_above 637 | 638 | for x in [20]: 639 | for y in [30,21,22,23]: 640 | T[x-1, y-1] *= shorter_above 641 | T[y-1, x-1] *= shorter_above 642 | for x in [32]: 643 | for y in [30,21,22,23]: 644 | T[x-1, y-1] *= shorter_above 645 | T[y-1, x-1] *= shorter_above 646 | for x in [19]: 647 | for y in [22]: 648 | T[x-1, y-1] *= shorter_above 649 | T[y-1, x-1] *= shorter_above 650 | for x in [17]: 651 | for y in [22,23]: 652 | T[x-1, y-1] *= shorter_above 653 | T[y-1, x-1] *= shorter_above 654 | for x in [29]: 655 | for y in [22,23]: 656 | T[x-1, y-1] *= shorter_above 657 | T[y-1, x-1] *= shorter_above 658 | 659 | if ring_above_middle < 1.0: 660 | ring_above_middles = [[2,7],[6,11],[2,11], 661 | [15,18],[19,22],[15,22]] 662 | for x in ring_above_middles: 663 | T[x[0]-1, x[1]-1] *= ring_above_middle 664 | T[x[1]-1, x[0]-1] *= ring_above_middle 665 | 666 | if middle_above_ring < 1.0: 667 | middle_above_rings = [[6,3],[10,7],[10,3], 668 | [19,14],[23,18],[23,14]] 669 | for x in middle_above_rings: 670 | T[x[0]-1, x[1]-1] *= middle_above_ring 671 | T[x[1]-1, x[0]-1] *= middle_above_ring 672 | 673 | # 10. Avoid using the same finger. 674 | # 1 2 3 4 25 28 13 14 15 16 31 675 | # 5 6 7 8 26 29 17 18 19 20 32 676 | # 9 10 11 12 27 30 21 22 23 24 677 | if same_finger < 1.0: 678 | same_fingers = [[1,5],[5,9],[1,9], [2,6],[6,10],[2,10], 679 | [3,7],[7,11],[3,11], [4,8],[8,12],[4,12], 680 | [25,26],[26,27],[25,27], [28,29],[29,30],[28,30], [31,32], 681 | [4,25],[4,26],[4,27], [8,25],[8,26],[8,27], [12,25],[12,26],[12,27], 682 | [13,28],[13,29],[13,30], [17,28],[17,29],[17,30], [21,28],[21,29],[21,30], 683 | [31,16],[31,20],[31,24], [32,16],[32,20],[32,24], 684 | [13,17],[17,21],[13,21], [14,18],[18,22],[14,22], 685 | [15,19],[19,23],[15,23], [16,20],[20,24],[16,24]] 686 | for x in same_fingers: 687 | T[x[0]-1, x[1]-1] *= same_finger 688 | T[x[1]-1, x[0]-1] *= same_finger 689 | 690 | # 11. Avoid the upper and lower rows. 691 | if not_home_row < 1.0: 692 | not_home_row_keys = [1,2,3,4,25, 9,10,11,12,27, 28,13,14,15,16,31, 30,21,22,23,24] 693 | for x in not_home_row_keys: 694 | for j in range(0,32): 695 | T[x-1, j] *= not_home_row 696 | T[j, x-1] *= not_home_row 697 | 698 | # 12. Avoid skipping over the home row. 699 | # 1 2 3 4 25 28 13 14 15 16 31 700 | # 5 6 7 8 26 29 17 18 19 20 32 701 | # 9 10 11 12 27 30 21 22 23 24 702 | if skip_row_0away < 1.0: 703 | skip_top = [1, 2, 3, 4, 4,25,25, 28,28,13,13,14,15,16,31] 704 | skip_bot = [9,10,11,12,27,12,27, 30,21,30,21,22,23,24,24] 705 | for ix, x in enumerate(skip_top): 706 | y = skip_bot[ix] 707 | T[x-1, y-1] *= skip_row_0away 708 | T[y-1, x-1] *= skip_row_0away 709 | if skip_row_1away < 1.0: 710 | skip_top = [1, 2, 2, 3, 3, 4, 4,25, 28,13,13,14,14,15,15,16,31] 711 | skip_bot = [10,9,11,10,12,11,27,11, 22,30,22,21,23,22,24,23,23] 712 | for ix, x in enumerate(skip_top): 713 | y = skip_bot[ix] 714 | T[x-1, y-1] *= skip_row_1away 715 | T[y-1, x-1] *= skip_row_1away 716 | if skip_row_2away < 1.0: 717 | skip_top = [1, 2,3, 4,25, 28,13,14,15,16,31] 718 | skip_bot = [11,12,9,10,10, 23,23,24,21,22,22] 719 | for ix, x in enumerate(skip_top): 720 | y = skip_bot[ix] 721 | T[x-1, y-1] *= skip_row_2away 722 | T[y-1, x-1] *= skip_row_2away 723 | if skip_row_3away < 1.0: 724 | skip_top = [1, 4,25, 28,13,16,16,31,31] 725 | skip_bot = [12,9, 9, 24,24,21,30,21,30] 726 | for ix, x in enumerate(skip_top): 727 | y = skip_bot[ix] 728 | T[x-1, y-1] *= skip_row_3away 729 | T[y-1, x-1] *= skip_row_3away 730 | 731 | Flow32x32 = T 732 | 733 | # Normalize matrix with min-max scaling to a range with maximum = 1: 734 | newMin = np.min(Flow32x32) / np.max(Flow32x32) 735 | newMax = 1.0 736 | Flow32x32 = newMin + (Flow32x32 - np.min(Flow32x32)) * (newMax - newMin) / (np.max(Flow32x32) - np.min(Flow32x32)) 737 | 738 | return Flow32x32 739 | 740 | Flow32x32 = create_32x32_flow_matrix(not_home_row, side_top, 741 | side_above_3away, side_above_2away, side_above_1away, middle_above_ring, ring_above_middle, outward, 742 | skip_row_3away, skip_row_2away, skip_row_1away, skip_row_0away, same_finger, lateral, same_hand, 743 | shorter_above, adjacent_offset, inside_top, index_above) 744 | 745 | # Print: 746 | print_matrix_info(matrix_data=Flow32x32, matrix_label="Flow32x32", nkeys=32, nlines=30) 747 | heatmap(data=Flow32x32, title="Flow32x32", xlabel="Key 1", ylabel="Key 2", print_output=print_output) 748 | -------------------------------------------------------------------------------- /code/load_interkey_speeds24x24.py: -------------------------------------------------------------------------------- 1 | # Left/right symmetric version of the Time24x24 matrix 2 | # (The original version was constructed with data from right-handed people.) 3 | # A. Iseri, M. Eksioglu / International Journal of Industrial Ergonomics 48 (2015) 127e138 4 | 5 | # Left: Right: 6 | # 1 2 3 4 13 14 15 16 7 | # 5 6 7 8 17 18 19 20 8 | # 9 10 11 12 21 22 23 24 9 | 10 | I = [ 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12, 16,15,14,13, 20,19,18,17, 24,23,22,21] 11 | J = [16,15,14,13, 20,19,18,17, 24,23,22,21, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12] 12 | 13 | TimeSymmetric24x24 = np.ones((24,24)) 14 | for i1, I1 in enumerate(I): 15 | for i2, I2 in enumerate(I): 16 | J1 = J[i1] - 1 17 | J2 = J[i2] - 1 18 | avgvalue = (Time24x24[I1-1,I2-1] + Time24x24[J1,J2]) / 2 19 | #print(Time24x24[I1-1,I2-1], Time24x24[J1,J2], avgvalue) 20 | TimeSymmetric24x24[I1-1,I2-1] = avgvalue 21 | TimeSymmetric24x24[J1,J2] = avgvalue 22 | 23 | # Normalize matrix with min-max scaling to a range with maximum = 1: 24 | newMin = np.min(Time24x24) / np.max(Time24x24) 25 | newMax = 1.0 26 | Time24x24 = newMin + (Time24x24 - np.min(Time24x24)) * (newMax - newMin) / (np.max(Time24x24) - np.min(Time24x24)) 27 | 28 | # Convert relative interkey stroke times to relative speeds by subtracting from 1: 29 | Speed24x24 = 1 - Time24x24 + np.min(Time24x24) 30 | 31 | # Normalize matrix with min-max scaling to a range with maximum = 1: 32 | newMin = np.min(TimeSymmetric24x24) / np.max(TimeSymmetric24x24) 33 | newMax = 1.0 34 | TimeSymmetric24x24 = newMin + (TimeSymmetric24x24 - np.min(TimeSymmetric24x24)) * (newMax - newMin) / (np.max(TimeSymmetric24x24) - np.min(TimeSymmetric24x24)) 35 | 36 | # Convert relative interkey stroke times to relative speeds by subtracting from 1: 37 | SpeedSymmetric24x24 = 1 - TimeSymmetric24x24 + np.min(TimeSymmetric24x24) 38 | 39 | # Print: 40 | #print_matrix_info(matrix_data=Speed24x24, matrix_label="Speed24x24", nkeys=24, nlines=50) 41 | #heatmap(data=Speed24x24, title="Speed24x24", xlabel="Key 1", ylabel="Key 2", print_output=print_output) -------------------------------------------------------------------------------- /code/load_interkey_speeds32x32.py: -------------------------------------------------------------------------------- 1 | # Left/right symmetric version of the Time32x32 matrix 2 | # (The original version was constructed with data from right-handed people.) 3 | # A. Iseri, M. Eksioglu / International Journal of Industrial Ergonomics 48 (2015) 127e138 4 | 5 | # Left: Right: 6 | # 1 2 3 4 25 28 13 14 15 16 31 7 | # 5 6 7 8 26 29 17 18 19 20 32 8 | # 9 10 11 12 27 30 21 22 23 24 9 | 10 | I = [ 1, 2, 3, 4,25, 5, 6, 7, 8,26, 9,10,11,12,27, 16,15,14,13,28, 20,19,18,17,29, 24,23,22,21,30] 11 | J = [16,15,14,13,28, 20,19,18,17,29, 24,23,22,21,30, 1, 2, 3, 4,25, 5, 6, 7, 8,26, 9,10,11,12,27] 12 | 13 | TimeSymmetric32x32 = np.ones((32,32)) 14 | for i1, I1 in enumerate(I): 15 | for i2, I2 in enumerate(I): 16 | J1 = J[i1] - 1 17 | J2 = J[i2] - 1 18 | avgvalue = (Time32x32[I1-1,I2-1] + Time32x32[J1,J2]) / 2 19 | #print(Time32x32[I1-1,I2-1], Time32x32[J1,J2], avgvalue) 20 | TimeSymmetric32x32[I1-1,I2-1] = avgvalue 21 | TimeSymmetric32x32[J1,J2] = avgvalue 22 | 23 | # Normalize matrix with min-max scaling to a range with maximum = 1: 24 | newMin = np.min(Time32x32) / np.max(Time32x32) 25 | newMax = 1.0 26 | Time32x32 = newMin + (Time32x32 - np.min(Time32x32)) * (newMax - newMin) / (np.max(Time32x32) - np.min(Time32x32)) 27 | 28 | # Convert relative interkey stroke times to relative speeds by subtracting from 1: 29 | Speed32x32 = 1 - Time32x32 + np.min(Time32x32) 30 | 31 | # Normalize matrix with min-max scaling to a range with maximum = 1: 32 | newMin = np.min(TimeSymmetric32x32) / np.max(TimeSymmetric32x32) 33 | newMax = 1.0 34 | TimeSymmetric32x32 = newMin + (TimeSymmetric32x32 - np.min(TimeSymmetric32x32)) * (newMax - newMin) / (np.max(TimeSymmetric32x32) - np.min(TimeSymmetric32x32)) 35 | 36 | # Convert relative interkey stroke times to relative speeds by subtracting from 1: 37 | SpeedSymmetric32x32 = 1 - TimeSymmetric32x32 + np.min(TimeSymmetric32x32) 38 | 39 | # Print: 40 | #print_matrix_info(matrix_data=Speed32x32, matrix_label="Speed32x32", nkeys=32, nlines=50) 41 | #heatmap(data=Speed32x32, title="Speed32x32", xlabel="Key 1", ylabel="Key 2", print_output=print_output) -------------------------------------------------------------------------------- /code/load_original_interkey_speeds.py: -------------------------------------------------------------------------------- 1 | # Inter-key timings. Save Time32x32 and Time24x24 arrays in data/ files. 2 | 3 | #Time32x32 = interkey_times32x32 + np.transpose(np.tri(32,32, -1) * interkey_times32x32) 4 | #Time32x32 = np.ndarray.tolist(Time32x32) 5 | #for times in Time32x32: 6 | # times_strings = [str(np.int(x)) for x in times] 7 | # print(','.join(times_strings)) 8 | 9 | interkey_timings32x32 = np.array([ 10 | [196,266,357,225,258,325,204,231,263,164,166,186,155,163,196,179,174,169,169,156,171,176,156,175,178,158,177,186,163,185,189,196], 11 | [266,196,271,239,240,267,196,208,208,160,166,169,167,156,168,153,148,143,143,129,145,150,129,149,151,132,151,160,137,159,163,170], 12 | [357,271,196,289,245,236,237,201,194,165,160,161,164,167,160,181,176,171,171,157,173,178,157,177,179,160,179,188,164,187,191,198], 13 | [225,239,289,181,245,296,182,196,229,147,150,167,149,152,175,171,166,162,162,148,163,169,148,167,170,150,169,178,155,177,182,188], 14 | [258,240,245,245,181,256,194,183,184,161,149,150,151,153,153,147,142,138,138,124,139,145,124,144,146,126,145,154,131,153,158,164], 15 | [325,267,236,296,256,181,214,215,184,185,147,157,162,154,148,175,170,166,166,152,167,173,152,172,174,154,173,182,159,181,186,192], 16 | [204,196,237,182,194,214,170,232,263,149,155,166,149,147,171,166,162,157,157,143,158,164,143,163,165,145,164,173,150,172,177,184], 17 | [231,208,201,196,183,215,232,170,239,157,149,151,164,146,150,143,138,134,134,120,135,141,120,140,142,122,141,150,127,149,154,160], 18 | [263,208,194,229,184,184,263,239,170,234,170,150,248,161,149,169,164,159,159,145,161,166,145,165,167,148,167,176,153,175,179,186], 19 | [164,160,165,147,161,185,149,157,234,169,226,257,251,240,276,164,159,154,154,141,156,162,141,160,163,143,162,171,148,170,175,181], 20 | [166,166,160,150,149,147,155,149,170,226,169,221,235,231,254,142,138,133,133,119,135,140,119,139,141,122,141,150,126,149,153,160], 21 | [186,169,161,167,150,157,166,151,150,257,221,169,262,228,235,162,157,153,153,139,154,160,139,159,161,141,160,169,146,168,173,179], 22 | [155,167,164,149,151,162,149,164,248,251,235,262,169,221,255,167,163,158,158,144,159,165,144,164,166,146,165,175,151,173,178,185], 23 | [163,156,167,152,153,154,147,146,161,240,231,228,221,169,228,166,161,156,156,142,158,163,142,162,164,145,164,173,150,172,176,183], 24 | [196,168,160,175,153,148,171,150,149,276,254,235,255,228,169,174,170,165,165,151,166,172,151,171,173,153,172,182,158,181,185,192], 25 | [179,153,181,171,147,175,166,143,169,164,142,162,167,166,174,151,203,216,196,213,226,145,153,220,139,142,185,149,160,148,155,157], 26 | [174,148,176,166,142,170,162,138,164,159,138,157,163,161,170,203,151,200,191,201,218,144,147,188,149,153,148,154,148,146,150,155], 27 | [169,143,171,162,138,166,157,134,159,154,133,153,158,156,165,216,200,151,207,188,198,144,144,140,137,139,138,176,152,148,161,167], 28 | [169,143,171,162,138,166,157,134,159,154,133,153,158,156,165,196,191,207,151,188,213,147,151,204,141,142,162,145,164,145,149,154], 29 | [156,129,157,148,124,152,143,120,145,141,119,139,144,142,151,213,201,188,188,151,192,137,133,149,136,138,139,147,152,143,144,165], 30 | [171,145,173,163,139,167,158,135,161,156,135,154,159,158,166,226,218,198,213,192,151,149,145,140,155,145,142,164,160,175,145,151], 31 | [176,150,178,169,145,173,164,141,166,162,140,160,165,163,172,145,144,144,147,137,149,151,207,227,189,191,208,209,206,226,197,181], 32 | [156,129,157,148,124,152,143,120,145,141,119,139,144,142,151,153,147,144,151,133,145,207,151,204,188,179,183,206,183,194,201,213], 33 | [175,149,177,167,144,172,163,140,165,160,139,159,164,162,171,220,188,140,204,149,140,227,204,151,226,185,175,268,220,265,188,205], 34 | [178,151,179,170,146,174,165,142,167,163,141,161,166,164,173,139,149,137,141,136,155,189,188,226,157,210,239,253,231,225,276,254], 35 | [158,132,160,150,126,154,145,122,148,143,122,141,146,145,153,142,153,139,142,138,145,191,179,185,210,157,208,251,240,235,229,273], 36 | [177,151,179,169,145,173,164,141,167,162,141,160,165,164,172,185,148,138,162,139,142,208,183,175,239,208,157,362,293,265,230,279], 37 | [186,160,188,178,154,182,173,150,176,171,150,169,175,173,182,149,154,176,145,147,164,209,206,268,253,251,362,170,233,236,271,291], 38 | [163,137,164,155,131,159,150,127,153,148,126,146,151,150,158,160,148,152,164,152,160,206,183,220,231,240,293,233,170,230,242,260], 39 | [185,159,187,177,153,181,172,149,175,170,149,168,173,172,181,148,146,148,145,143,175,226,194,265,225,235,265,236,230,170,230,245], 40 | [189,163,191,182,158,186,177,154,179,175,153,173,178,176,185,155,150,161,149,144,145,197,201,188,276,229,230,271,242,230,170,226], 41 | [196,170,198,188,164,192,184,160,186,181,160,179,185,183,192,157,155,167,154,165,151,181,213,205,254,273,279,291,260,245,226,170]]) 42 | 43 | # Extract pairwise entries for the 32 vertical range keys: 44 | # Left: Right: 45 | # 1 2 3 4 25 28 13 14 15 16 31 46 | # 5 6 7 8 26 29 17 18 19 20 32 47 | # 9 10 11 12 27 30 21 22 23 24 48 | # 49 | # A. Iseri, M. Eksioglu. Intl Journal of Industrial Ergonomics 48 (2015) 127e138 50 | # Left: Right: 51 | # 1 4 7 10 13 16 19 22 25 28 30 32 52 | # 2 5 8 11 14 17 20 23 26 29 31 53 | # 3 6 9 12 15 18 21 24 27 54 | map_table_to_engram_32keys = [ 1, 4, 7,10, 2, 5, 8,11, 3, 6, 9,12, 55 | 19,22,25,28, 20,23,26,29, 21,24,27,31, 56 | 13,14,15, 16,17,18, 30,32] 57 | Time32x32 = np.zeros((32,32)) 58 | u = 0 59 | for i in map_table_to_engram_32keys: 60 | u += 1 61 | v = 0 62 | for j in map_table_to_engram_32keys: 63 | v += 1 64 | Time32x32[u-1,v-1] = interkey_timings32x32[i-1,j-1] 65 | 66 | # Extract pairwise entries for the 24 vertical range keys: 67 | map_table_to_engram_24keys = [ 1, 4, 7,10, 2, 5, 8,11, 3, 6, 9,12, 68 | 19,22,25,28, 20,23,26,29, 21,24,27,31] 69 | Time24x24 = np.zeros((24,24)) 70 | u = 0 71 | for i in map_table_to_engram_24keys: 72 | u += 1 73 | v = 0 74 | for j in map_table_to_engram_24keys: 75 | v += 1 76 | Time24x24[u-1,v-1] = interkey_timings32x32[i-1,j-1] 77 | 78 | # Print: 79 | for times in Time32x32: 80 | times = [np.str(np.int(x)) for x in times] 81 | print('[{0}],'.format(','.join(times))) 82 | print('') 83 | for times in Time24x24: 84 | times = [np.str(np.int(x)) for x in times] 85 | print('[{0}],'.format(','.join(times))) -------------------------------------------------------------------------------- /code/load_strength_data.py: -------------------------------------------------------------------------------- 1 | # Normalize by the highest peak force (middle finger): 2 | middle_force = 2.36 3 | index_force = 2.26 4 | ring_force = 2.02 5 | little_force = 1.84 6 | middle_norm = 1.0 7 | index_norm = index_force / middle_force 8 | ring_norm = ring_force / middle_force 9 | little_norm = little_force / middle_force 10 | print('index/middle: {0}'.format(index_norm)) 11 | print('ring/middle: {0}'.format(ring_norm)) 12 | print('little/middle: {0}'.format(little_norm)) 13 | 14 | # Relative left/right hand strength (assume equal): 15 | lf = 1.0 16 | rf = 1.0 17 | 18 | strengths24 = np.array(( 19 | lf * little_norm, lf * ring_norm, lf * middle_norm, lf * index_norm, 20 | lf * little_norm, lf * ring_norm, lf * middle_norm, lf * index_norm, 21 | lf * little_norm, lf * ring_norm, lf * middle_norm, lf * index_norm, 22 | rf * index_norm, rf * middle_norm, rf * ring_norm, rf * little_norm, 23 | rf * index_norm, rf * middle_norm, rf * ring_norm, rf * little_norm, 24 | rf * index_norm, rf * middle_norm, rf * ring_norm, rf * little_norm)) 25 | 26 | # Create a finger-pair position strength matrix by adding pairs of strength values: 27 | Strength24x24 = np.zeros((24, 24)) 28 | for i in range(24): 29 | Strength24x24[i,:] = strengths24 30 | Strength24x24 = (Strength24x24 + Strength24x24.transpose()) 31 | 32 | # Normalize matrix with min-max scaling to a range with maximum = 1: 33 | #newMin = strength_factor 34 | newMin = min_strength_factor # np.min(Strength24x24) / np.max(Strength24x24) 35 | newMax = 1.0 36 | Strength24x24 = newMin + (Strength24x24 - np.min(Strength24x24)) * (newMax - newMin) / (np.max(Strength24x24) - np.min(Strength24x24)) 37 | 38 | # Print: 39 | print_matrix_info(matrix_data=Strength24x24, matrix_label="Strength24x24", nkeys=24, nlines=10) 40 | heatmap(data=Strength24x24, title="Strength24x24", xlabel="Key 1", ylabel="Key 2", print_output=print_output) 41 | 42 | 43 | penalty = 1.0 # Penalty for lateral (index, little) finger placement (1 = no penalty) 44 | 45 | strengths32 = np.array((lf * little_norm, lf * ring_norm, lf * middle_norm, lf * index_norm, 46 | lf * little_norm, lf * ring_norm, lf * middle_norm, lf * index_norm, 47 | lf * little_norm, lf * ring_norm, lf * middle_norm, lf * index_norm, 48 | rf * index_norm, rf * middle_norm, rf * ring_norm, rf * little_norm, 49 | rf * index_norm, rf * middle_norm, rf * ring_norm, rf * little_norm, 50 | rf * index_norm, rf * middle_norm, rf * ring_norm, rf * little_norm, 51 | lf * index_norm * penalty, lf * index_norm * penalty, lf * index_norm * penalty, 52 | rf * index_norm * penalty, rf * index_norm * penalty, rf * index_norm * penalty, 53 | rf * little_norm * penalty, rf * little_norm * penalty)) 54 | 55 | # Create a finger-pair position strength matrix by adding pairs of strength values: 56 | Strength32x32 = np.zeros((32, 32)) 57 | for i in range(32): 58 | Strength32x32[i,:] = strengths32 59 | Strength32x32 = (Strength32x32 + Strength32x32.transpose()) 60 | 61 | # Normalize matrix with min-max scaling to a range with maximum = 1: 62 | newMin = np.min(Strength32x32) / np.max(Strength32x32) 63 | newMax = 1.0 64 | Strength32x32 = newMin + (Strength32x32 - np.min(Strength32x32)) * (newMax - newMin) / (np.max(Strength32x32) - np.min(Strength32x32)) 65 | 66 | # Print: 67 | print_matrix_info(matrix_data=Strength32x32, matrix_label="Strength32x32", nkeys=32, nlines=10) 68 | heatmap(data=Strength32x32, title="Strength32x32", xlabel="Key 1", ylabel="Key 2", print_output=print_output) -------------------------------------------------------------------------------- /code/rank_layouts.py: -------------------------------------------------------------------------------- 1 | layout_strings = [] 2 | scores = [] 3 | for layout in top_layouts: 4 | layout_string = ' '.join(layout) 5 | score = score_layout(Factors24x24, layout, bigrams, bigram_frequencies, verbose=False) 6 | #print(' {0} {1}'.format(layout_string, score)) 7 | layout_strings.append(layout_string) 8 | scores.append(score) 9 | 10 | # Establish which layouts are within a small difference of the top-scoring layout 11 | scores_sorted, ranks_sorted, Isort = rank_within_epsilon(scores, factor32, factor=True, verbose=False) 12 | layouts_sorted = [] 13 | layout_strings_sorted = [] 14 | for i in Isort: 15 | layouts_sorted.append(top_layouts[i]) 16 | layout_strings_sorted.append(layout_strings[i]) 17 | print('\n Rank Score') 18 | for i, rank in enumerate(ranks_sorted): 19 | print(' {0}: {1} {2}'.format(rank, layout_strings_sorted[i], scores_sorted[i])) 20 | 21 | print('\nLayouts tied for first place, with letter frequencies:\n') 22 | print(' Rank Score') 23 | first_ranks = [] 24 | first_layouts = [] 25 | first_layout_strings = [] 26 | first_scores = [] 27 | for i, rank in enumerate(ranks_sorted): 28 | if rank == 1: 29 | first_ranks.append(rank) 30 | first_layouts.append(layout_strings_sorted[i]) 31 | first_layout_strings.append(layouts_sorted[i]) 32 | first_scores.append(scores_sorted[i]) 33 | Isort2 = np.argsort([-x for x in first_scores]) 34 | first_ranks_sorted = [] 35 | first_layouts_sorted = [] 36 | first_layout_strings_sorted = [] 37 | first_scores_sorted = [] 38 | for i in Isort2: 39 | first_ranks_sorted.append(first_ranks[i]) 40 | first_layouts_sorted.append(first_layouts[i]) 41 | first_layout_strings_sorted.append(first_layout_strings[i]) 42 | first_scores_sorted.append(first_scores[i]) 43 | for i, first_layout in enumerate(first_layouts): 44 | print(' {0}: {1} {2}'.format(first_ranks_sorted[i], 45 | first_layout, # first_layout_strings_sorted[i], 46 | first_scores_sorted[i])) 47 | # Print layouts: 48 | for i, layout_string in enumerate(first_layout_strings_sorted): 49 | layout = first_layouts_sorted[i] 50 | print('') 51 | print_layout24(layout_string) 52 | print('') 53 | print_layout24_instances(layout_string, letters24, instances24, bigrams, bigram_frequencies) 54 | print('') -------------------------------------------------------------------------------- /code/test/remove_parameters_rescore.py: -------------------------------------------------------------------------------- 1 | params0 = [side_above_3away, side_above_2away, side_above_1away, middle_above_ring, ring_above_middle, 2 | outward, skip_row_3away, skip_row_2away, skip_row_1away, skip_row_0away, same_finger] 3 | param_names = ['side_above_3away', 'side_above_2away', 'side_above_1away', 4 | 'middle_above_ring', 'ring_above_middle', 'outward', 'skip_row_3away', 5 | 'skip_row_2away', 'skip_row_1away', 'skip_row_0away', 'same_finger'] 6 | params_lists = [] 7 | for i in range(len(params0)): 8 | params_list = params0.copy() 9 | params_list[i] = 1.0 10 | params_lists.append(params_list) 11 | 12 | for iparam, P in enumerate(params_lists): 13 | 14 | print(' Remove parameter {0}:'.format(param_names[iparam])) 15 | 16 | data_matrix_param = create_24x24_flow_matrix(not_home_row, side_top, 17 | P[0],P[1],P[2],P[3],P[4],P[5],P[6],P[7],P[8],P[9],P[10], 18 | 1,1,1,1,1,1) 19 | if apply_strength: 20 | data_matrix_param = Strength24x24 * data_matrix_param 21 | 22 | param_scores = [] 23 | for letters in test_layout_strings: 24 | score = score_layout(data_matrix_param, letters, bigrams, bigram_frequencies, verbose=False); 25 | param_scores.append(score) 26 | #print(letters, score) 27 | 28 | param_scores_sorted, param_ranks_sorted, Isort_param = rank_within_epsilon(param_scores, factor24, factor=True, verbose=False) 29 | param_layouts_sorted = [] 30 | param_layout_strings_sorted = [] 31 | for i in Isort_param: 32 | param_layouts_sorted.append(' '.join(test_layout_strings[i])) 33 | param_layout_strings_sorted.append(test_layout_strings[i]) 34 | 35 | print(' Layout Score') 36 | for i, isort_param in enumerate(Isort_param): 37 | if param_ranks_sorted[isort_param] == 1: 38 | if isort_param < 9: 39 | s = ' ' 40 | else: 41 | s = ' ' 42 | print(' ({0}){1}{2} {3}'.format(isort_param+1, s, 43 | param_layouts_sorted[i], 44 | param_scores_sorted[i])) -------------------------------------------------------------------------------- /code/test/score_speed_of_layouts.py: -------------------------------------------------------------------------------- 1 | data_matrix_speed = Speed24x24 2 | speed_scores = [] 3 | for letters in test_layout_strings: 4 | score = score_layout(data_matrix_speed, letters, bigrams, bigram_frequencies, verbose = False) 5 | speed_scores.append(score) 6 | 7 | speed_scores_sorted, speed_ranks_sorted, Isort_speed = rank_within_epsilon(speed_scores, 8 | epsilon, factor=False, verbose=False) 9 | speed_layouts_sorted = [] 10 | speed_layout_strings_sorted = [] 11 | for i in Isort_speed: 12 | speed_layouts_sorted.append(' '.join(test_layout_strings[i])) 13 | speed_layout_strings_sorted.append(test_layout_strings[i]) 14 | 15 | count = 0 16 | print(' Layout Speed score') 17 | for i, isort_speed in enumerate(Isort_speed): 18 | if speed_ranks_sorted[isort_speed] == 1: 19 | count += 1 20 | if isort_speed < 9: 21 | s = ' ' 22 | else: 23 | s = ' ' 24 | print(' ({0}){1}{2} {3}'.format(isort_speed+1, s, 25 | speed_layouts_sorted[i], 26 | speed_scores_sorted[i])) 27 | print(' {0} of {1} layouts tied for first place'.format(count, len(test_layout_strings))) -------------------------------------------------------------------------------- /code/test/score_strength_of_layouts.py: -------------------------------------------------------------------------------- 1 | data_matrix_strength = Strength24x24 2 | strength_scores = [] 3 | for letters in test_layout_strings: 4 | score = score_layout(data_matrix_strength, letters, bigrams, bigram_frequencies, verbose = False) 5 | strength_scores.append(score) 6 | 7 | strength_scores_sorted, strength_ranks_sorted, Isort_strength = rank_within_epsilon(strength_scores, 8 | factor32, factor=True, verbose=False) 9 | strength_layouts_sorted = [] 10 | strength_layout_strings_sorted = [] 11 | for i in Isort_strength: 12 | strength_layouts_sorted.append(' '.join(test_layout_strings[i])) 13 | strength_layout_strings_sorted.append(test_layout_strings[i]) 14 | 15 | print(' Layout Strength score') 16 | count = 0 17 | for i, isort_strength in enumerate(Isort_strength): 18 | if strength_ranks_sorted[isort_strength] == 1: 19 | count += 1 20 | if isort_strength < 9: 21 | s = ' ' 22 | else: 23 | s = ' ' 24 | print(' ({0}){1}{2} {3}'.format(isort_strength+1, s, 25 | strength_layouts_sorted[i], 26 | strength_scores_sorted[i])) 27 | print(' {0} of {1} layouts tied for first place'.format(count, len(test_layout_strings))) -------------------------------------------------------------------------------- /code/website-typing-test/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | ## ChatGPT prompts to build this website: 4 | 5 | ---- 6 | 7 | Create a website with provided text prominently displayed in black color with a highly visible and legible font. The visitor to the website must type the provided text, but is not permitted to hit the backspace, return, tab, or arrow keys or correct any mistakes -- the visitor can only keep typing. As the visitor types each character (corresponding to a letter, number, space, symbol, or punctuation mark) in the provided text, the character on the screen changes color. If the visitor types the correct key, the character changes color to green. If the visitor types an incorrect key, the character changes color to red. The website logs the timing of each keystroke with millisecond precision. The website displays the following information as a table below the text, formatted as follows. Each row corresponds to a character and the following are filled in for the columns: (1) character from the provided text, (2) character the visitor typed, (3) the number 1 if these two match each other and 0 if they don't, (4) a time stamp when the key is pressed, (5) a time stamp when the key is released. Please create the necessary documents for such a website with as few dependencies and in the simplest way possible. 8 | 9 | The resulting website displays the text and the column headers for the table, but when I start typing, it searches the page rather than change the colors of the text. Also, the text is legible, but the table text is too bold and prominent. 10 | 11 | At the top of the page display the text "Please touch type the following text as you would usually type -- at your usual typing speed on a keyboard of your choice. Each correctly typed character will turn green and each incorrectly typed character will turn red. You will not be able to go back or correct any mistakes. Just keep typing until you have finished." 12 | 13 | ---- 14 | 15 | ## Input text for website visitor 16 | 17 | At an average typing speed of 40 words per minute where a word is on average 5 characters, a person can type approximately 1,000 characters in 5 minutes. 18 | 19 | ChatGPT prompt: "Generate a random text string containing 1,000 characters with only lowercase letters and the following punctuation marks , . / ; ' and include a space after every 5 characters." 20 | 21 | Resulting code is in generate_string.py 22 | 23 | Resulting random string: 24 | 25 | p'uco wnqum i/min crj'i gt;pl pwvd. pxlxm 'smdq g[cgo ivat; jh[ud vdizb bskts nnotb dw';, u,ko. ocm/z hld.p h/cur cenvd vj/sn h/,y. gz;an mlrgm dt,.n wajf/ /r'xi /h'pp qiwvt hcb/u 'gcg[ 'yqra khbdq tfdf; sojp, zm[wj ;sj[y pczzo ktji; iegid xjkk/ ;vm.i l''n/ h'cyx sk.'f iutza 'ydf, gtqga fvuie gyqy. v[h,; ebj[/ mkzwt icw[x txliv px.c[ wurbg ./krh o.hli a;cqv nntp; rix[. wrxhq 'lmni hwhza urg[' fs[v/ qeldu eol'f ugqgu y'hbk wuqr; gd'xf c,'im l.;hs [qyt' c/yhf w'lj/ tttbg '[qp. vkvb/ .qspv .nfg' mohw. t[ntx c.qlf /o'qb b;ygs defu. y;gnv ghiz' yly.. z;mm[ cgj/w qkei, xo;uf qqjmk zqp;k cgko; .dkbn rpihv pb;[s wbiem u,lsz vabzy ,obqm tmtoj p/;[u rz;[o c/k,[ ;/;vy qsxmr c.xrd ybtm[ e'[/h amfq/ [yxnc z'prc mox'a thvnn gofxr e.tfm i.pyb xrauq kv,vs nnyed sd[hs miwfp cknsf jvxxm qeba, dquls myprm ;'qpc ;;c,. .a.[p r/qvc jo'mg ahhet ,jk'u wo.c. qtzlr ;'i., hjp/n ztpkc j;qxw l;vl, tc;lr ;qwx. utq,' rlack ddcwu i;u/j jaskd ixeye r;[s' bhpdv pulbw qcyp/ pahls yirfi xl[oz ss;xx ,gt'u ,avqm pemkd rpdk -------------------------------------------------------------------------------- /code/website-typing-test/generate_string.py: -------------------------------------------------------------------------------- 1 | import string 2 | import random 3 | 4 | def generate_random_string_with_specific_chars(length): 5 | # Characters that can be typed without the Shift key, only lowercase and specified punctuation 6 | chars = string.ascii_lowercase + ",./;'[" 7 | 8 | # Initialize the string and count for spaces 9 | random_string = '' 10 | space_count = 0 11 | 12 | for _ in range(length): 13 | # Add a space after every 5 characters on average 14 | if space_count >= 5: 15 | random_string += ' ' 16 | space_count = 0 17 | else: 18 | random_string += random.choice(chars) 19 | space_count += 1 20 | 21 | return random_string 22 | 23 | # Generate a new string with the specified characters 24 | random_text_specific = generate_random_string_with_specific_chars(1000) 25 | print(random_text_specific) 26 | len(random_text_specific) # Check the length of the generated string including spaces 27 | -------------------------------------------------------------------------------- /code/website-typing-test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Typing Test 7 | 8 | 9 | 10 |
11 |

Please touch type the following text as you would usually type -- at your usual typing speed on a keyboard of your choice. Each correctly typed character will turn green and each incorrectly typed character will turn red. You will not be able to go back or correct any mistakes. Just keep typing until you have finished.

12 |
13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
Expected CharTyped CharMatchTimestamp (Press)Timestamp (Release)
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /code/website-typing-test/script.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', () => { 2 | const textToType = "p'uco wnqum i/min crj'i gt;pl pwvd. pxlxm 'smdq g[cgo ivat; jh[ud vdizb bskts nnotb dw';, u,ko. ocm/z hld.p h/cur cenvd vj/sn h/,y. gz;an mlrgm dt,.n wajf/ /r'xi /h'pp qiwvt hcb/u 'gcg[ 'yqra khbdq tfdf; sojp, zm[wj ;sj[y pczzo ktji; iegid xjkk/ ;vm.i l''n/ h'cyx sk.'f iutza 'ydf, gtqga fvuie gyqy. v[h,; ebj[/ mkzwt icw[x txliv px.c[ wurbg ./krh o.hli a;cqv nntp; rix[. wrxhq 'lmni hwhza urg[' fs[v/ qeldu eol'f ugqgu y'hbk wuqr; gd'xf c,'im l.;hs [qyt' c/yhf w'lj/ tttbg '[qp. vkvb/ .qspv .nfg' mohw. t[ntx c.qlf /o'qb b;ygs defu. y;gnv ghiz' yly.. z;mm[ cgj/w qkei, xo;uf qqjmk zqp;k cgko; .dkbn rpihv pb;[s wbiem u,lsz vabzy ,obqm tmtoj p/;[u rz;[o c/k,[ ;/;vy qsxmr c.xrd ybtm[ e'[/h amfq/ [yxnc z'prc mox'a thvnn gofxr e.tfm i.pyb xrauq kv,vs nnyed sd[hs miwfp cknsf jvxxm qeba, dquls myprm ;'qpc ;;c,. .a.[p r/qvc jo'mg ahhet ,jk'u wo.c. qtzlr ;'i., hjp/n ztpkc j;qxw l;vl, tc;lr ;qwx. utq,' rlack ddcwu i;u/j jaskd ixeye r;[s' bhpdv pulbw qcyp/ pahls yirfi xl[oz ss;xx ,gt'u ,avqm pemkd rpdk"; // Replace with your text 3 | const container = document.getElementById('text-container'); 4 | container.innerHTML = textToType.split('').map(char => `${char}`).join(''); 5 | 6 | let currentIndex = 0; 7 | const keystrokeData = []; 8 | 9 | document.addEventListener('keydown', (e) => { 10 | e.preventDefault(); // Prevent default browser actions 11 | if (['Backspace', 'Tab', 'ArrowLeft', 'ArrowRight', 'Enter'].includes(e.key)) { 12 | return; // Still prevent the use of these keys 13 | } 14 | 15 | const keyPressTime = new Date().getTime(); 16 | const currentChar = textToType[currentIndex]; 17 | const span = container.getElementsByTagName('span')[currentIndex]; 18 | const isCorrect = e.key === currentChar; 19 | 20 | span.className = isCorrect ? 'correct' : 'incorrect'; 21 | 22 | keystrokeData.push({ 23 | expected: currentChar, 24 | typed: e.key, 25 | match: isCorrect ? 1 : 0, 26 | pressTime: keyPressTime, 27 | releaseTime: null // This will be filled on keyup 28 | }); 29 | 30 | currentIndex++; 31 | updateTable(); 32 | }); 33 | 34 | document.addEventListener('keyup', (e) => { 35 | const keyReleaseTime = new Date().getTime(); 36 | if (keystrokeData[currentIndex - 1]) { 37 | keystrokeData[currentIndex - 1].releaseTime = keyReleaseTime; 38 | updateTable(); 39 | } 40 | }); 41 | 42 | function updateTable() { 43 | const tbody = document.getElementById('keystroke-data').getElementsByTagName('tbody')[0]; 44 | tbody.innerHTML = ''; 45 | keystrokeData.forEach(data => { 46 | const row = tbody.insertRow(); 47 | Object.values(data).forEach(text => { 48 | const cell = row.insertCell(); 49 | cell.appendChild(document.createTextNode(text)); 50 | }); 51 | }); 52 | } 53 | }); 54 | -------------------------------------------------------------------------------- /code/website-typing-test/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | margin: 0; 7 | padding: 0; 8 | } 9 | 10 | #instructions { 11 | margin: 20px; 12 | padding: 10px; 13 | text-align: left; /* Left-justify the instructions */ 14 | width: 80%; /* Adjust width as needed */ 15 | } 16 | 17 | #text-container { 18 | color: black; 19 | border: 1px solid #ddd; 20 | padding: 20px; 21 | margin: 20px 0; 22 | font-size: 1.5em; /* Increase the size of the provided text */ 23 | width: 80%; /* Adjust width as needed */ 24 | } 25 | 26 | .correct { 27 | color: green; 28 | } 29 | 30 | .incorrect { 31 | color: red; 32 | } 33 | 34 | table { 35 | border-collapse: collapse; 36 | width: 60%; /* Make table smaller */ 37 | font-size: 0.8em; /* Decrease font size in the table */ 38 | margin-top: 500px; /* Push the table far down the page */ 39 | } 40 | 41 | th, td { 42 | border: 1px solid black; 43 | text-align: left; 44 | padding: 8px; 45 | } 46 | -------------------------------------------------------------------------------- /data/Time24x24.py: -------------------------------------------------------------------------------- 1 | # code/load_original_interkey_speeds.py 2 | # Left: Right: 3 | # 1 2 3 4 25 28 13 14 15 16 31 4 | # 5 6 7 8 26 29 17 18 19 20 32 5 | # 9 10 11 12 27 30 21 22 23 24 6 | Time24x24 = np.array([ 7 | [196,225,204,164,266,258,231,166,357,325,263,186,169,176,178,186,156,156,158,163,171,175,177,189], 8 | [225,181,182,147,239,245,196,150,289,296,229,167,162,169,170,178,148,148,150,155,163,167,169,182], 9 | [204,182,170,149,196,194,232,155,237,214,263,166,157,164,165,173,143,143,145,150,158,163,164,177], 10 | [164,147,149,169,160,161,157,226,165,185,234,257,154,162,163,171,141,141,143,148,156,160,162,175], 11 | [266,239,196,160,196,240,208,166,271,267,208,169,143,150,151,160,129,129,132,137,145,149,151,163], 12 | [258,245,194,161,240,181,183,149,245,256,184,150,138,145,146,154,124,124,126,131,139,144,145,158], 13 | [231,196,232,157,208,183,170,149,201,215,239,151,134,141,142,150,120,120,122,127,135,140,141,154], 14 | [166,150,155,226,166,149,149,169,160,147,170,221,133,140,141,150,119,119,122,126,135,139,141,153], 15 | [357,289,237,165,271,245,201,160,196,236,194,161,171,178,179,188,157,157,160,164,173,177,179,191], 16 | [325,296,214,185,267,256,215,147,236,181,184,157,166,173,174,182,152,152,154,159,167,172,173,186], 17 | [263,229,263,234,208,184,239,170,194,184,170,150,159,166,167,176,145,145,148,153,161,165,167,179], 18 | [186,167,166,257,169,150,151,221,161,157,150,169,153,160,161,169,139,139,141,146,154,159,160,173], 19 | [169,162,157,154,143,138,134,133,171,166,159,153,151,147,141,145,188,151,142,164,213,204,162,149], 20 | [176,169,164,162,150,145,141,140,178,173,166,160,147,151,189,209,137,207,191,206,149,227,208,197], 21 | [178,170,165,163,151,146,142,141,179,174,167,161,141,189,157,253,136,188,210,231,155,226,239,276], 22 | [186,178,173,171,160,154,150,150,188,182,176,169,145,209,253,170,147,206,251,233,164,268,362,271], 23 | [156,148,143,141,129,124,120,119,157,152,145,139,188,137,136,147,151,133,138,152,192,149,139,144], 24 | [156,148,143,141,129,124,120,119,157,152,145,139,151,207,188,206,133,151,179,183,145,204,183,201], 25 | [158,150,145,143,132,126,122,122,160,154,148,141,142,191,210,251,138,179,157,240,145,185,208,229], 26 | [163,155,150,148,137,131,127,126,164,159,153,146,164,206,231,233,152,183,240,170,160,220,293,242], 27 | [171,163,158,156,145,139,135,135,173,167,161,154,213,149,155,164,192,145,145,160,151,140,142,145], 28 | [175,167,163,160,149,144,140,139,177,172,165,159,204,227,226,268,149,204,185,220,140,151,175,188], 29 | [177,169,164,162,151,145,141,141,179,173,167,160,162,208,239,362,139,183,208,293,142,175,157,230], 30 | [189,182,177,175,163,158,154,153,191,186,179,173,149,197,276,271,144,201,229,242,145,188,230,170]]) -------------------------------------------------------------------------------- /data/Time32x32.py: -------------------------------------------------------------------------------- 1 | # code/load_original_interkey_speeds.py 2 | # Left: Right: 3 | # 1 2 3 4 25 28 13 14 15 16 31 4 | # 5 6 7 8 26 29 17 18 19 20 32 5 | # 9 10 11 12 27 30 21 22 23 24 6 | Time32x32 = np.array([ 7 | [196,225,204,164,266,258,231,166,357,325,263,186,169,176,178,186,156,156,158,163,171,175,177,189,155,163,196,179,174,169,185,196], 8 | [225,181,182,147,239,245,196,150,289,296,229,167,162,169,170,178,148,148,150,155,163,167,169,182,149,152,175,171,166,162,177,188], 9 | [204,182,170,149,196,194,232,155,237,214,263,166,157,164,165,173,143,143,145,150,158,163,164,177,149,147,171,166,162,157,172,184], 10 | [164,147,149,169,160,161,157,226,165,185,234,257,154,162,163,171,141,141,143,148,156,160,162,175,251,240,276,164,159,154,170,181], 11 | [266,239,196,160,196,240,208,166,271,267,208,169,143,150,151,160,129,129,132,137,145,149,151,163,167,156,168,153,148,143,159,170], 12 | [258,245,194,161,240,181,183,149,245,256,184,150,138,145,146,154,124,124,126,131,139,144,145,158,151,153,153,147,142,138,153,164], 13 | [231,196,232,157,208,183,170,149,201,215,239,151,134,141,142,150,120,120,122,127,135,140,141,154,164,146,150,143,138,134,149,160], 14 | [166,150,155,226,166,149,149,169,160,147,170,221,133,140,141,150,119,119,122,126,135,139,141,153,235,231,254,142,138,133,149,160], 15 | [357,289,237,165,271,245,201,160,196,236,194,161,171,178,179,188,157,157,160,164,173,177,179,191,164,167,160,181,176,171,187,198], 16 | [325,296,214,185,267,256,215,147,236,181,184,157,166,173,174,182,152,152,154,159,167,172,173,186,162,154,148,175,170,166,181,192], 17 | [263,229,263,234,208,184,239,170,194,184,170,150,159,166,167,176,145,145,148,153,161,165,167,179,248,161,149,169,164,159,175,186], 18 | [186,167,166,257,169,150,151,221,161,157,150,169,153,160,161,169,139,139,141,146,154,159,160,173,262,228,235,162,157,153,168,179], 19 | [169,162,157,154,143,138,134,133,171,166,159,153,151,147,141,145,188,151,142,164,213,204,162,149,158,156,165,196,191,207,145,154], 20 | [176,169,164,162,150,145,141,140,178,173,166,160,147,151,189,209,137,207,191,206,149,227,208,197,165,163,172,145,144,144,226,181], 21 | [178,170,165,163,151,146,142,141,179,174,167,161,141,189,157,253,136,188,210,231,155,226,239,276,166,164,173,139,149,137,225,254], 22 | [186,178,173,171,160,154,150,150,188,182,176,169,145,209,253,170,147,206,251,233,164,268,362,271,175,173,182,149,154,176,236,291], 23 | [156,148,143,141,129,124,120,119,157,152,145,139,188,137,136,147,151,133,138,152,192,149,139,144,144,142,151,213,201,188,143,165], 24 | [156,148,143,141,129,124,120,119,157,152,145,139,151,207,188,206,133,151,179,183,145,204,183,201,144,142,151,153,147,144,194,213], 25 | [158,150,145,143,132,126,122,122,160,154,148,141,142,191,210,251,138,179,157,240,145,185,208,229,146,145,153,142,153,139,235,273], 26 | [163,155,150,148,137,131,127,126,164,159,153,146,164,206,231,233,152,183,240,170,160,220,293,242,151,150,158,160,148,152,230,260], 27 | [171,163,158,156,145,139,135,135,173,167,161,154,213,149,155,164,192,145,145,160,151,140,142,145,159,158,166,226,218,198,175,151], 28 | [175,167,163,160,149,144,140,139,177,172,165,159,204,227,226,268,149,204,185,220,140,151,175,188,164,162,171,220,188,140,265,205], 29 | [177,169,164,162,151,145,141,141,179,173,167,160,162,208,239,362,139,183,208,293,142,175,157,230,165,164,172,185,148,138,265,279], 30 | [189,182,177,175,163,158,154,153,191,186,179,173,149,197,276,271,144,201,229,242,145,188,230,170,178,176,185,155,150,161,230,226], 31 | [155,149,149,251,167,151,164,235,164,162,248,262,158,165,166,175,144,144,146,151,159,164,165,178,169,221,255,167,163,158,173,185], 32 | [163,152,147,240,156,153,146,231,167,154,161,228,156,163,164,173,142,142,145,150,158,162,164,176,221,169,228,166,161,156,172,183], 33 | [196,175,171,276,168,153,150,254,160,148,149,235,165,172,173,182,151,151,153,158,166,171,172,185,255,228,169,174,170,165,181,192], 34 | [179,171,166,164,153,147,143,142,181,175,169,162,196,145,139,149,213,153,142,160,226,220,185,155,167,166,174,151,203,216,148,157], 35 | [174,166,162,159,148,142,138,138,176,170,164,157,191,144,149,154,201,147,153,148,218,188,148,150,163,161,170,203,151,200,146,155], 36 | [169,162,157,154,143,138,134,133,171,166,159,153,207,144,137,176,188,144,139,152,198,140,138,161,158,156,165,216,200,151,148,167], 37 | [185,177,172,170,159,153,149,149,187,181,175,168,145,226,225,236,143,194,235,230,175,265,265,230,173,172,181,148,146,148,170,245], 38 | [196,188,184,181,170,164,160,160,198,192,186,179,154,181,254,291,165,213,273,260,151,205,279,226,185,183,192,157,155,167,245,170]]) -------------------------------------------------------------------------------- /data/bigram_counts_PeterNorvig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/data/bigram_counts_PeterNorvig.png -------------------------------------------------------------------------------- /data/bigram_frequencies.txt: -------------------------------------------------------------------------------- 1 | [3.55620339e-02 3.07474124e-02 2.43274529e-02 2.04826481e-02 2 | 1.98515108e-02 1.85432319e-02 1.75804642e-02 1.48673230e-02 3 | 1.45424846e-02 1.35228145e-02 1.34257882e-02 1.33939375e-02 4 | 1.27653906e-02 1.20486963e-02 1.17497528e-02 1.16812337e-02 5 | 1.12842988e-02 1.12327374e-02 1.08744953e-02 1.07489847e-02 6 | 1.05347566e-02 1.04126653e-02 1.04125115e-02 9.53014842e-03 7 | 9.32114579e-03 9.25763559e-03 8.71095073e-03 8.70002319e-03 8 | 8.34931851e-03 8.29254235e-03 8.25280566e-03 7.93859725e-03 9 | 7.93006486e-03 7.64818391e-03 7.63241814e-03 7.27618866e-03 10 | 7.26724441e-03 6.98707488e-03 6.91722265e-03 6.88165290e-03 11 | 6.85633031e-03 6.51417363e-03 6.24352184e-03 5.97765978e-03 12 | 5.76571076e-03 5.76283716e-03 5.65269345e-03 5.50057242e-03 13 | 5.46256885e-03 5.42747781e-03 5.38164098e-03 5.30301559e-03 14 | 5.29886071e-03 5.27529444e-03 5.08937452e-03 4.92966405e-03 15 | 4.87753568e-03 4.84902069e-03 4.77989185e-03 4.77282719e-03 16 | 4.74470916e-03 4.64574958e-03 4.60971757e-03 4.54257059e-03 17 | 4.47772200e-03 4.42103298e-03 4.31534618e-03 4.25820178e-03 18 | 4.25013516e-03 4.15745843e-03 4.12608242e-03 4.05151268e-03 19 | 4.05075209e-03 3.97732158e-03 3.96527277e-03 3.94413046e-03 20 | 3.86884200e-03 3.85337077e-03 3.85189513e-03 3.84646388e-03 21 | 3.78793431e-03 3.77605408e-03 3.74420703e-03 3.73663638e-03 22 | 3.67956418e-03 3.65492648e-03 3.61676413e-03 3.61373182e-03 23 | 3.60899233e-03 3.47234973e-03 3.45829494e-03 3.39212478e-03 24 | 3.37488213e-03 3.36877623e-03 3.30478042e-03 3.23572471e-03 25 | 3.17759946e-03 3.17691369e-03 3.16447752e-03 3.15240004e-03 26 | 3.15172398e-03 3.11176534e-03 2.95503911e-03 2.89966768e-03 27 | 2.87848219e-03 2.86282435e-03 2.84865969e-03 2.84585627e-03 28 | 2.81484803e-03 2.69544349e-03 2.62987083e-03 2.54961380e-03 29 | 2.54906719e-03 2.54783715e-03 2.52606379e-03 2.47740122e-03 30 | 2.39175226e-03 2.36573195e-03 2.33400171e-03 2.29786417e-03 31 | 2.27503360e-03 2.27277101e-03 2.23911052e-03 2.21754315e-03 32 | 2.18017446e-03 2.17360835e-03 2.14044590e-03 2.13767970e-03 33 | 2.13188615e-03 2.10259217e-03 2.04932647e-03 2.04724906e-03 34 | 2.03256516e-03 2.02845908e-03 1.96777866e-03 1.95449429e-03 35 | 1.95410531e-03 1.91254221e-03 1.89316385e-03 1.88234971e-03 36 | 1.87652262e-03 1.84944194e-03 1.83351654e-03 1.78086545e-03 37 | 1.76468430e-03 1.75132925e-03 1.71573739e-03 1.70683303e-03 38 | 1.66405086e-03 1.63999785e-03 1.62732115e-03 1.62613977e-03 39 | 1.60361051e-03 1.54749379e-03 1.51636562e-03 1.51067364e-03 40 | 1.49901610e-03 1.49455831e-03 1.49011351e-03 1.48460771e-03 41 | 1.48077067e-03 1.47541326e-03 1.47480347e-03 1.46316579e-03 42 | 1.46204465e-03 1.43745726e-03 1.41513491e-03 1.39980075e-03 43 | 1.38382616e-03 1.36545598e-03 1.36333253e-03 1.36012483e-03 44 | 1.35189358e-03 1.32127808e-03 1.30185876e-03 1.28328757e-03 45 | 1.27907576e-03 1.26260675e-03 1.23637099e-03 1.23094105e-03 46 | 1.21386641e-03 1.20743055e-03 1.19536134e-03 1.19032774e-03 47 | 1.17626124e-03 1.16805780e-03 1.14618533e-03 1.11559852e-03 48 | 1.06597119e-03 1.05782134e-03 1.04699320e-03 1.04540205e-03 49 | 1.01153313e-03 9.97734501e-04 9.86028683e-04 9.84491816e-04 50 | 9.79174450e-04 9.78784303e-04 9.70343472e-04 9.68322624e-04 51 | 9.66708177e-04 9.60690121e-04 9.59749105e-04 9.43900197e-04 52 | 9.40242103e-04 9.28331656e-04 9.26685761e-04 9.14014864e-04 53 | 9.02555222e-04 8.92112065e-04 8.85803335e-04 8.77507468e-04 54 | 8.62646840e-04 8.57695087e-04 8.54499050e-04 8.43925356e-04 55 | 8.31382851e-04 8.23722323e-04 8.16643644e-04 7.89875969e-04 56 | 7.86444549e-04 7.42072946e-04 7.36927617e-04 7.27646949e-04 57 | 7.25004577e-04 7.11071849e-04 6.92833068e-04 6.71807283e-04 58 | 6.68638321e-04 6.56391013e-04 6.51990243e-04 6.49048818e-04 59 | 6.43397537e-04 6.43118050e-04 6.37839069e-04 6.21864133e-04 60 | 6.06367626e-04 5.99162639e-04 5.87024289e-04 5.74860663e-04 61 | 5.72519573e-04 5.68447140e-04 5.58806800e-04 5.45711864e-04 62 | 5.37896691e-04 5.34768852e-04 5.20071483e-04 5.18874875e-04 63 | 5.16054649e-04 5.14388309e-04 5.11931727e-04 5.04227393e-04 64 | 5.00890900e-04 4.97325634e-04 4.75088970e-04 4.66605249e-04 65 | 4.58324041e-04 4.29127437e-04 4.27514542e-04 4.17186146e-04 66 | 4.16199437e-04 3.94646924e-04 3.94183167e-04 3.86306652e-04 67 | 3.61812839e-04 3.50841120e-04 3.49059129e-04 3.23402665e-04 68 | 3.22604151e-04 3.11527347e-04 3.10032877e-04 3.07611603e-04 69 | 2.96010489e-04 2.88197255e-04 2.77494857e-04 2.70735751e-04 70 | 2.67122244e-04 2.64790886e-04 2.64597695e-04 2.63237166e-04 71 | 2.61362824e-04 2.59399816e-04 2.58614910e-04 2.57579773e-04 72 | 2.49143242e-04 2.49036616e-04 2.47547306e-04 2.36748821e-04 73 | 2.35282013e-04 2.32245156e-04 2.30209194e-04 2.28229670e-04 74 | 2.27822992e-04 2.20319919e-04 2.17945603e-04 2.13543715e-04 75 | 1.97145202e-04 1.90526970e-04 1.90304866e-04 1.88393786e-04 76 | 1.85754127e-04 1.85322815e-04 1.81767370e-04 1.74089940e-04 77 | 1.71644610e-04 1.71039222e-04 1.69557657e-04 1.66839046e-04 78 | 1.64718022e-04 1.59561636e-04 1.57658164e-04 1.54026397e-04 79 | 1.52211752e-04 1.51115808e-04 1.47564559e-04 1.46841709e-04 80 | 1.36432949e-04 1.35005671e-04 1.32141796e-04 1.27573620e-04 81 | 1.27432415e-04 1.26388914e-04 1.25919175e-04 1.23965197e-04 82 | 1.21174483e-04 1.18691292e-04 1.18219114e-04 1.17637524e-04 83 | 1.17526303e-04 1.13037594e-04 1.10863960e-04 1.09331046e-04 84 | 1.08837112e-04 1.06567401e-04 1.05698197e-04 1.00512685e-04 85 | 1.00106518e-04 9.85814937e-05 9.17495595e-05 9.15174736e-05 86 | 9.09807382e-05 8.79007001e-05 8.16240791e-05 7.91627682e-05 87 | 7.79158645e-05 7.56940333e-05 7.44394656e-05 7.18101849e-05 88 | 6.97589276e-05 6.81802488e-05 6.69029567e-05 6.54143249e-05 89 | 6.08786925e-05 6.07607969e-05 6.03570614e-05 5.98994801e-05 90 | 5.95001291e-05 5.94970869e-05 5.86983574e-05 5.79700512e-05 91 | 5.66119466e-05 5.50952209e-05 5.47453912e-05 5.43839597e-05 92 | 5.25861529e-05 4.89722417e-05 4.78187439e-05 4.77415865e-05 93 | 4.77107257e-05 4.62616737e-05 4.60653783e-05 4.60409299e-05 94 | 4.56730211e-05 4.54645078e-05 4.52324283e-05 4.38982745e-05 95 | 4.36906610e-05 4.33593810e-05 4.31226640e-05 4.29912118e-05 96 | 4.29446346e-05 4.17137339e-05 3.93478837e-05 3.84895449e-05 97 | 3.84390172e-05 3.81834469e-05 3.53827628e-05 3.47222349e-05 98 | 3.37168917e-05 3.18518637e-05 3.15951703e-05 3.12905207e-05 99 | 3.10605585e-05 3.02567524e-05 2.91709879e-05 2.89567711e-05 100 | 2.85652293e-05 2.82994071e-05 2.80417376e-05 2.77861205e-05 101 | 2.77303518e-05 2.76273746e-05 2.72172235e-05 2.69880432e-05 102 | 2.66503046e-05 2.66033916e-05 2.62086568e-05 2.59259584e-05 103 | 2.57640153e-05 2.56299050e-05 2.54449453e-05 2.51909823e-05 104 | 2.47409597e-05 2.46797892e-05 2.42472084e-05 2.35748710e-05 105 | 2.24438116e-05 2.24317329e-05 2.23097275e-05 2.21249597e-05 106 | 2.17815183e-05 2.15248592e-05 2.09465192e-05 2.09125513e-05 107 | 1.96913177e-05 1.95330853e-05 1.91064697e-05 1.88952009e-05 108 | 1.85746459e-05 1.81220081e-05 1.78919334e-05 1.73267658e-05 109 | 1.61874055e-05 1.60765855e-05 1.58740992e-05 1.45486411e-05 110 | 1.40812264e-05 1.36678429e-05 1.32768479e-05 1.31460479e-05 111 | 1.30872012e-05 1.29588223e-05 1.25748548e-05 1.24146066e-05 112 | 1.22821602e-05 1.22486357e-05 1.20714645e-05 1.20448925e-05 113 | 1.19866728e-05 1.18936663e-05 1.17590888e-05 1.17001978e-05 114 | 1.16346360e-05 1.11092945e-05 1.08992577e-05 1.06740258e-05 115 | 1.06735218e-05 1.06144296e-05 1.05679067e-05 1.03656570e-05 116 | 1.03317955e-05 9.98437559e-06 9.01036943e-06 8.85768061e-06 117 | 8.76035160e-06 8.60019167e-06 8.19227801e-06 7.80479658e-06 118 | 7.53516931e-06 7.44150882e-06 7.30644125e-06 7.26777599e-06 119 | 7.06747616e-06 6.95177332e-06 6.85925126e-06 6.74132156e-06 120 | 6.71322068e-06 6.70106994e-06 6.66133186e-06 6.47626505e-06 121 | 6.38130476e-06 6.29576510e-06 6.24612583e-06 5.93271496e-06 122 | 5.92132104e-06 5.83947722e-06 5.76779879e-06 5.76465728e-06 123 | 5.53187023e-06 5.47131015e-06 5.33180695e-06 5.22417954e-06 124 | 5.20732008e-06 5.15949060e-06 5.11569104e-06 4.95336950e-06 125 | 4.94557425e-06 4.73636484e-06 4.63955858e-06 4.53340156e-06 126 | 4.22935422e-06 4.19307790e-06 4.17347414e-06 4.12142146e-06 127 | 4.11855764e-06 3.80541311e-06 3.36707879e-06 3.29563656e-06 128 | 3.17577578e-06 3.05442971e-06 2.98983688e-06 2.97762691e-06 129 | 2.95066092e-06 2.91720550e-06 2.89840858e-06 2.77497857e-06 130 | 2.76265227e-06 2.74176112e-06 2.70310579e-06 2.61648976e-06 131 | 2.60275585e-06 2.56616744e-06 2.55465117e-06 2.49712549e-06 132 | 2.42815484e-06 2.37933375e-06 2.35040476e-06 2.33914845e-06 133 | 2.33036549e-06 2.32978989e-06 2.28930419e-06 2.28804340e-06 134 | 2.26346210e-06 2.24353844e-06 2.23182640e-06 2.23165865e-06 135 | 2.22696341e-06 2.22115030e-06 2.21572164e-06 2.20668084e-06 136 | 2.19243658e-06 2.17382266e-06 2.08159887e-06 2.07762818e-06 137 | 1.95415065e-06 1.88693410e-06 1.83219245e-06 1.81431726e-06 138 | 1.67631850e-06 1.67169206e-06 1.63803449e-06 1.57770706e-06 139 | 1.56577585e-06 1.53130790e-06 1.52519015e-06 1.52439998e-06 140 | 1.49350905e-06 1.47212210e-06 1.45715861e-06 1.40331777e-06 141 | 1.38641504e-06 1.29786439e-06 1.27069447e-06 1.25613209e-06 142 | 1.23105569e-06 1.22268909e-06 1.21688094e-06 1.18065108e-06 143 | 1.18060143e-06 1.16794389e-06 1.13216621e-06 1.12716419e-06 144 | 1.12418866e-06 1.12412659e-06 1.05684621e-06 1.05049722e-06 145 | 1.04986594e-06 1.03676402e-06 1.03482230e-06 9.96847192e-07 146 | 9.75926251e-07 9.54397081e-07 9.36101632e-07 9.30100914e-07 147 | 9.27467975e-07 8.92801774e-07 8.85217179e-07 8.58891337e-07 148 | 7.80484800e-07 7.67724409e-07 7.54031637e-07 7.45052550e-07 149 | 7.32511689e-07 7.06828122e-07 6.59585949e-07 6.40055245e-07 150 | 6.18628925e-07 6.17142222e-07 6.09904832e-07 6.07242457e-07 151 | 5.72270900e-07 5.49823535e-07 5.22568859e-07 5.01838721e-07 152 | 4.91372576e-07 4.82981856e-07 4.69688423e-07 4.59727658e-07 153 | 4.54795508e-07 4.22875379e-07 4.13494116e-07 3.99834682e-07 154 | 3.97288987e-07 3.87644926e-07 3.84245584e-07 3.81268632e-07 155 | 3.67029696e-07 3.57267536e-07 3.52642869e-07 3.51058992e-07 156 | 3.44112772e-07 3.36167495e-07 3.24215712e-07 3.23810344e-07 157 | 3.21814716e-07 3.21505459e-07 3.10936465e-07 2.88018831e-07 158 | 2.86309762e-07 2.76140106e-07 2.63218703e-07 2.56899508e-07 159 | 2.51244222e-07 2.25386521e-07 2.15766576e-07 2.03018243e-07 160 | 1.99078411e-07 1.97551987e-07 1.96981706e-07 1.92415912e-07 161 | 1.84391194e-07 1.81253585e-07 1.78663913e-07 1.77747846e-07 162 | 1.59541769e-07 1.38003378e-07 1.36499298e-07 1.22889160e-07 163 | 1.22576357e-07 1.19711121e-07 1.09597855e-07 9.97477409e-08 164 | 9.65292710e-08 9.36271510e-08 9.35785637e-08 9.34540807e-08 165 | 8.40270671e-08 7.82629028e-08 7.54898762e-08 6.64058115e-08 166 | 5.96748649e-08 5.79118882e-08 5.73650143e-08 5.65688198e-08 167 | 5.34673852e-08 5.34237630e-08 5.29956976e-08 4.84174907e-08 168 | 3.83818937e-08] -------------------------------------------------------------------------------- /data/bigrams-trigrams-frequencies.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/data/bigrams-trigrams-frequencies.xlsx -------------------------------------------------------------------------------- /data/bigrams.txt: -------------------------------------------------------------------------------- 1 | ['TH' 'HE' 'IN' 'ER' 'AN' 'RE' 'ON' 'AT' 'EN' 'ND' 'TI' 'ES' 'OR' 'TE' 2 | 'OF' 'ED' 'IS' 'IT' 'AL' 'AR' 'ST' 'TO' 'NT' 'NG' 'SE' 'HA' 'AS' 'OU' 3 | 'IO' 'LE' 'VE' 'CO' 'ME' 'DE' 'HI' 'RI' 'RO' 'IC' 'NE' 'EA' 'RA' 'CE' 4 | 'LI' 'CH' 'LL' 'BE' 'MA' 'SI' 'OM' 'UR' 'CA' 'EL' 'TA' 'LA' 'NS' 'DI' 5 | 'FO' 'HO' 'PE' 'EC' 'PR' 'NO' 'CT' 'US' 'AC' 'OT' 'IL' 'TR' 'LY' 'NC' 6 | 'ET' 'UT' 'SS' 'SO' 'RS' 'UN' 'LO' 'WA' 'GE' 'IE' 'WH' 'EE' 'WI' 'EM' 7 | 'AD' 'OL' 'RT' 'PO' 'WE' 'NA' 'UL' 'NI' 'TS' 'MO' 'OW' 'PA' 'IM' 'MI' 8 | 'AI' 'SH' 'IR' 'SU' 'ID' 'OS' 'IV' 'IA' 'AM' 'FI' 'CI' 'VI' 'PL' 'IG' 9 | 'TU' 'EV' 'LD' 'RY' 'MP' 'FE' 'BL' 'AB' 'GH' 'TY' 'OP' 'WO' 'SA' 'AY' 10 | 'EX' 'KE' 'FR' 'OO' 'AV' 'AG' 'IF' 'AP' 'GR' 'OD' 'BO' 'SP' 'RD' 'DO' 11 | 'UC' 'BU' 'EI' 'OV' 'BY' 'RM' 'EP' 'TT' 'OC' 'FA' 'EF' 'CU' 'RN' 'SC' 12 | 'GI' 'DA' 'YO' 'CR' 'CL' 'DU' 'GA' 'QU' 'UE' 'FF' 'BA' 'EY' 'LS' 'VA' 13 | 'UM' 'PP' 'UA' 'UP' 'LU' 'GO' 'HT' 'RU' 'UG' 'DS' 'LT' 'PI' 'RC' 'RR' 14 | 'EG' 'AU' 'CK' 'EW' 'MU' 'BR' 'BI' 'PT' 'AK' 'PU' 'UI' 'RG' 'IB' 'TL' 15 | 'NY' 'KI' 'RK' 'YS' 'OB' 'MM' 'FU' 'PH' 'OG' 'MS' 'YE' 'UD' 'MB' 'IP' 16 | 'UB' 'OI' 'RL' 'GU' 'DR' 'HR' 'CC' 'TW' 'FT' 'WN' 'NU' 'AF' 'HU' 'NN' 17 | 'EO' 'VO' 'RV' 'NF' 'XP' 'GN' 'SM' 'FL' 'IZ' 'OK' 'NL' 'MY' 'GL' 'AW' 18 | 'JU' 'OA' 'EQ' 'SY' 'SL' 'PS' 'JO' 'LF' 'NV' 'JE' 'NK' 'KN' 'GS' 'DY' 19 | 'HY' 'ZE' 'KS' 'XT' 'BS' 'IK' 'DD' 'CY' 'RP' 'SK' 'XI' 'OE' 'OY' 'WS' 20 | 'LV' 'DL' 'RF' 'EU' 'DG' 'WR' 'XA' 'YI' 'NM' 'EB' 'RB' 'TM' 'XC' 'EH' 21 | 'TC' 'GY' 'JA' 'HN' 'YP' 'ZA' 'GG' 'YM' 'SW' 'BJ' 'LM' 'CS' 'II' 'IX' 22 | 'XE' 'OH' 'LK' 'DV' 'LP' 'AX' 'OX' 'UF' 'DM' 'IU' 'SF' 'BT' 'KA' 'YT' 23 | 'EK' 'PM' 'YA' 'GT' 'WL' 'RH' 'YL' 'HS' 'AH' 'YC' 'YN' 'RW' 'HM' 'LW' 24 | 'HL' 'AE' 'ZI' 'AZ' 'LC' 'PY' 'AJ' 'IQ' 'NJ' 'BB' 'NH' 'UO' 'KL' 'LR' 25 | 'TN' 'GM' 'SN' 'NR' 'FY' 'MN' 'DW' 'SB' 'YR' 'DN' 'SQ' 'ZO' 'OJ' 'YD' 26 | 'LB' 'WT' 'LG' 'KO' 'NP' 'SR' 'NQ' 'KY' 'LN' 'NW' 'TF' 'FS' 'CQ' 'DH' 27 | 'SD' 'VY' 'DJ' 'HW' 'XU' 'AO' 'ML' 'UK' 'UY' 'EJ' 'EZ' 'HB' 'NZ' 'NB' 28 | 'MC' 'YB' 'TP' 'XH' 'UX' 'TZ' 'BV' 'MF' 'WD' 'OZ' 'YW' 'KH' 'GD' 'BM' 29 | 'MR' 'KU' 'UV' 'DT' 'HD' 'AA' 'XX' 'DF' 'DB' 'JI' 'KR' 'XO' 'CM' 'ZZ' 30 | 'NX' 'YG' 'XY' 'KG' 'TB' 'DC' 'BD' 'SG' 'WY' 'ZY' 'AQ' 'HF' 'CD' 'VU' 31 | 'KW' 'ZU' 'BN' 'IH' 'TG' 'XV' 'UZ' 'BC' 'XF' 'YZ' 'KM' 'DP' 'LH' 'WF' 32 | 'KF' 'PF' 'CF' 'MT' 'YU' 'CP' 'PB' 'TD' 'ZL' 'SV' 'HC' 'MG' 'PW' 'GF' 33 | 'PD' 'PN' 'PC' 'RX' 'TV' 'IJ' 'WM' 'UH' 'WK' 'WB' 'BH' 'OQ' 'KT' 'RQ' 34 | 'KB' 'CG' 'VR' 'CN' 'PK' 'UU' 'YF' 'WP' 'CZ' 'KP' 'DQ' 'WU' 'FM' 'WC' 35 | 'MD' 'KD' 'ZH' 'GW' 'RZ' 'CB' 'IW' 'XL' 'HP' 'MW' 'VS' 'FC' 'RJ' 'BP' 36 | 'MH' 'HH' 'YH' 'UJ' 'FG' 'FD' 'GB' 'PG' 'TK' 'KK' 'HQ' 'FN' 'LZ' 'VL' 37 | 'GP' 'HZ' 'DK' 'YK' 'QI' 'LX' 'VD' 'ZS' 'BW' 'XQ' 'MV' 'UW' 'HG' 'FB' 38 | 'SJ' 'WW' 'GK' 'UQ' 'BG' 'SZ' 'JR' 'QL' 'ZT' 'HK' 'VC' 'XM' 'GC' 'FW' 39 | 'PZ' 'KC' 'HV' 'XW' 'ZW' 'FP' 'IY' 'PV' 'VT' 'JP' 'CV' 'ZB' 'VP' 'ZR' 40 | 'FH' 'YV' 'ZG' 'ZM' 'ZV' 'QS' 'KV' 'VN' 'ZN' 'QA' 'YX' 'JN' 'BF' 'MK' 41 | 'CW' 'JM' 'LQ' 'JH' 'KJ' 'JC' 'GZ' 'JS' 'TX' 'FK' 'JL' 'VM' 'LJ' 'TJ' 42 | 'JJ' 'CJ' 'VG' 'MJ' 'JT' 'PJ' 'WG' 'VH' 'BK' 'VV' 'JD' 'TQ' 'VB' 'JF' 43 | 'DZ' 'XB' 'JB' 'ZC' 'FJ' 'YY' 'QN' 'XS' 'QR' 'JK' 'JV' 'QQ' 'XN' 'VF' 44 | 'PX' 'ZD' 'QT' 'ZP' 'QO' 'DX' 'HJ' 'GV' 'JW' 'QC' 'JY' 'GJ' 'QB' 'PQ' 45 | 'JG' 'BZ' 'MX' 'QM' 'MZ' 'QF' 'WJ' 'ZQ' 'XR' 'ZK' 'CX' 'FX' 'FV' 'BX' 46 | 'VW' 'VJ' 'MQ' 'QV' 'ZF' 'QE' 'YJ' 'GX' 'KX' 'XG' 'QD' 'XJ' 'SX' 'VZ' 47 | 'VX' 'WV' 'YQ' 'BQ' 'GQ' 'VK' 'ZJ' 'XK' 'QP' 'HX' 'FZ' 'QH' 'QJ' 'JZ' 48 | 'VQ' 'KQ' 'XD' 'QW' 'JX' 'QX' 'KZ' 'WX' 'FQ' 'XZ' 'ZX'] -------------------------------------------------------------------------------- /data/computer_language_char_frequency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/data/computer_language_char_frequency.png -------------------------------------------------------------------------------- /data/interkey-timings.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/data/interkey-timings.xlsx -------------------------------------------------------------------------------- /data/letter_counts_PeterNorvig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/data/letter_counts_PeterNorvig.png -------------------------------------------------------------------------------- /data/onegrams.txt: -------------------------------------------------------------------------------- 1 | ['E' 'T' 'A' 'O' 'I' 'N' 'S' 'R' 'H' 'L' 'D' 'C' 'U' 'M' 'F' 'P' 'G' 'W' 2 | 'Y' 'B' 'V' 'K' 'X' 'J' 'Q' 'Z'] -------------------------------------------------------------------------------- /install/README.md: -------------------------------------------------------------------------------- 1 | # Engram Install README 2 | 3 | You can install the Engram v2.0 layout on macOS, Windows, and Linux operating systems using [Keyman](https://keyman.com/keyboards/engram) 4 | (and [try it out online](https://keymanweb.com/#en,Keyboard_engram)). 5 | 6 | This folder contains alternative approaches for installing native Engram keymaps for different operating systems, thanks to the kind contributions of Engram users. 7 | 8 | Special thanks to the following contributors for their pull requests: 9 | 10 | - @sunaku: 11 | - Windows Microsoft Keyboard Layout Creator keymap 12 | - Linux xkb (X keyboard extension) keymap 13 | - @iklarman: MacOS Ukelele keymap 14 | - @AbbyRead: Windows Microsoft Keyboard Layout Creator keymap (#2) 15 | - @rfiga: Linux Gnome desktop environment 16 | - @Apsu: Documentation improvements 17 | 18 | -------------------------------------------------------------------------------- /install/ios/Engram.xkeyboard: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/ios/Engram.xkeyboard -------------------------------------------------------------------------------- /install/ios/README.md: -------------------------------------------------------------------------------- 1 | # iOS Implementation 2 | 3 | Using a small iOS app called [xKeyboard - Custom Keyboard](https://apps.apple.com/us/app/xkeyboard-custom-keyboard/id1440245962) by 煦 张, it is possible to create a custom on-screen layout for iOS. 4 | 5 | ![Engram on iPhone](https://raw.githubusercontent.com/binarybottle/engram/master/install/ios/engram2.webp) 6 | 7 | Try the following: 8 | 9 | 1. Download the [`.xkeyboard` file](https://raw.githubusercontent.com/binarybottle/engram/master/install/ios/Engram.xkeyboard) in this directory to your iOS device. 10 | 11 | 2. Install [xKeyboard - Custom Keyboard](https://apps.apple.com/us/app/xkeyboard-custom-keyboard/id1440245962) on your iOS device using the App Store. 12 | 13 | 3. Use the in-app purchase to upgrade to the paid version. (Required to be able to install from an `.xkeyboard` file.) 14 | 15 | 4. In the bottom row of buttons in xKeyboard, tap `Keyboards` (the middle button). 16 | 17 | 5. In the upper right corner, tap the `+` button, then `Import .xkeyboard`. 18 | 19 | 6. Navigate to the `.xkeyboard` file you downloaded in step 1, and tap to install. 20 | 21 | 7. Go to `Settings > General > Keyboard > Keyboards > Add New Keyboard` and tap `xKeyboard`. 22 | 23 | 8. Now you can use the globe in any app to switch to your Engram layout. 24 | 25 | 26 | There aro layouts for both iPhone and iPad, including portrait and landscape variations. 27 | 28 | ![Engram on iPad](https://raw.githubusercontent.com/binarybottle/engram/master/install/ios/engram1.webp) 29 | 30 | xKeyboard has a feature called "candidate keys" that allows you to press a key and get additional functionality. The iPhone layout uses candidate keys to collapse the center punctuation column on portrait iPhone view. They don't work quite as well as the native keyboard's flick-you kinda have to wait for the candidates to pop up. The dictionary and auto insertion of apostrophe's is also sorely missing. So the layout is slightly modified, but things are fitting ok on iPhone, and very well on iPad. 31 | -------------------------------------------------------------------------------- /install/ios/engram1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/ios/engram1.webp -------------------------------------------------------------------------------- /install/ios/engram2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/ios/engram2.webp -------------------------------------------------------------------------------- /install/ios/engram3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/ios/engram3.webp -------------------------------------------------------------------------------- /install/linux/x_keyboard_extension/Makefile: -------------------------------------------------------------------------------- 1 | TARGET_SYM := /usr/share/X11/xkb/symbols/us 2 | SOURCE_SYM := usr-share-X11-xkb-symbols-us 3 | TARGET_RULE := /usr/share/X11/xkb/rules/evdev.xml 4 | SOURCE_RULE := usr-share-X11-xkb-rules-evdev 5 | 6 | all: reinstall 7 | 8 | install: $(SOURCE_SYM) $(TARGET_SYM) $(SOURCE_RULE) $(TARGET_RULE) 9 | echo '//ENGRAM//BEGIN' >> $(TARGET_SYM) 10 | cat $(SOURCE_SYM) >> $(TARGET_SYM) 11 | echo '//ENGRAM//END' >> $(TARGET_SYM) 12 | sed -i "$$(awk '/variantList/ {print NR; exit}' $(TARGET_RULE)) r $(SOURCE_RULE)" $(TARGET_RULE) 13 | 14 | uninstall: $(TARGET_SYM) $(TARGET_RULE) 15 | sed -i '/^\/\/ENGRAM\/\/BEGIN$$/,/^\/\/ENGRAM\/\/END$$/d' $(TARGET_SYM) 16 | sed -i '/ENGRAM BEGIN/,/ENGRAM END/d' $(TARGET_RULE) 17 | 18 | reinstall: 19 | $(MAKE) uninstall 20 | $(MAKE) install 21 | 22 | .PHONY: all install uninstall reinstall 23 | -------------------------------------------------------------------------------- /install/linux/x_keyboard_extension/README.md: -------------------------------------------------------------------------------- 1 | ## Linux 2 | 3 | Install: 4 | 5 | sudo make install 6 | echo Now restart your X session. 7 | 8 | The Engram layout should be available under your desktop environment's keyboard selection utility. 9 | 10 | Activate: 11 | 12 | setxkbmap -layout us -variant engram # one layout; no switch 13 | setxkbmap -layout us,us -variant engram,basic # dual layout switching 14 | 15 | Reinstall (whenever a system-wide XKB package upgrade reverts installation): 16 | 17 | sudo make reinstall 18 | 19 | Uninstall: 20 | 21 | sudo make uninstall 22 | -------------------------------------------------------------------------------- /install/linux/x_keyboard_extension/usr-share-X11-xkb-rules-evdev: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | engram 5 | English (Engram) 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /install/linux/x_keyboard_extension/usr-share-X11-xkb-symbols-us: -------------------------------------------------------------------------------- 1 | // Arno's Engram keyboard layout v2.0 - https://engram.dev 2 | partial alphanumeric_keys 3 | xkb_symbols "engram" 4 | { 5 | include "us(basic)" 6 | 7 | key { [ bracketleft, braceleft ] }; // [{ 8 | key { [ 1, bar ] }; // 1| 9 | key { [ 2, equal ] }; // 2= 10 | key { [ 3, asciitilde ] }; // 3~ 11 | key { [ 4, plus ] }; // 4+ 12 | key { [ 5, less ] }; // 5< 13 | key { [ 6, greater ] }; // 6> 14 | key { [ 7, asciicircum ] }; // 7^ 15 | key { [ 8, ampersand ] }; // 8& 16 | key { [ 9, percent ] }; // 9% 17 | key { [ 0, asterisk ] }; // 0* 18 | key { [ bracketright, braceright ] }; // ]} 19 | key { [ slash, backslash ] }; // /\ 20 | 21 | key { [ b, B ] }; // bB 22 | key { [ y, Y ] }; // yY 23 | key { [ o, O ] }; // oO 24 | key { [ u, U ] }; // uU 25 | key { [ apostrophe, parenleft ] }; // '( 26 | key { [ quotedbl, parenright ] }; // ") 27 | key { [ l, L ] }; // lL 28 | key { [ d, D ] }; // dD 29 | key { [ w, W ] }; // wW 30 | key { [ v, V ] }; // vV 31 | key { [ z, Z ] }; // zZ 32 | key { [ numbersign, dollar ] }; // #$ 33 | key { [ at, grave ] }; // @` 34 | 35 | key { [ c, C ] }; // cC 36 | key { [ i, I ] }; // iI 37 | key { [ e, E ] }; // eE 38 | key { [ a, A ] }; // aA 39 | key { [ comma, semicolon ] }; // ,; 40 | key { [ period, colon ] }; // .: 41 | key { [ h, H ] }; // hH 42 | key { [ t, T ] }; // tT 43 | key { [ s, S ] }; // sS 44 | key { [ n, N ] }; // nN 45 | key { [ q, Q ] }; // qQ 46 | 47 | key { [ g, G ] }; // gG 48 | key { [ x, X ] }; // xX 49 | key { [ j, J ] }; // jJ 50 | key { [ k, K ] }; // kK 51 | key { [ minus, underscore ] }; // -_ 52 | key { [ question, exclam ] }; // ?! 53 | key { [ r, R ] }; // rR 54 | key { [ m, M ] }; // mM 55 | key { [ f, F ] }; // fF 56 | key { [ p, P ] }; // pP 57 | }; 58 | -------------------------------------------------------------------------------- /install/mac/karabiner/README.md: -------------------------------------------------------------------------------- 1 | # Engram Config for Karabiner 2 | 3 | Engram layouts for Karabiner. 4 | 5 | 6 | ```ts 7 | [{ 1| 2= 3~ 4+ 5< 6> 7^ 8& 9% 0* ]} 8 | bB yY oO uU '( ") lL dD wW vV zZ #$ @` 9 | ⌃cC ⌥iI ⌘eE ⇧aA ,; .: ⇧hH ⌘tT ⌥sS ⌃nN qQ 10 | gG xX jJ kK -_ ?! rR mM fF pP /\ 11 | ⌫ ␣ ⏎ 12 | ``` 13 | 14 | 15 | # Using Karabiner with Engram 16 | 17 | To use the vanilla Engram layout on MacOS, simply 18 | 19 | 1. Install Karabiner `brew install karabiner-elements` (you'll have to grant necessary permissions in `System Settings`, detailed on the [Karabiner website](https://karabiner-elements.pqrs.org)). 20 | 2. Click this link to open the Engram layout [directly in Karabiner](https://smote.io/install_engram.html) 21 | 22 | Or you can view the JSON [here](https://raw.githubusercontent.com/binarybottle/engram/master/install/mac/karabiner/engram.json) (you'll need to place the json file in `~/.config/karabiner/assets/complex_modifications/` and maybe restart Karabiner if you want to customize/ install manually). 23 | 24 | 25 | ## Using a karabiner.json Generator 26 | 27 | This directory also includes [Karabiner.ts](https://github.com/evan-liu/karabiner.ts) config, as well as a [Goku](https://github.com/yqrashawn/GokuRakuJoudo) config. 28 | 29 | Home Row Mods are working better in the Karabiner.ts config than the Goku one. (They're configured as simlayers in the Karabiner.ts version.) Karabiner.ts also 🏃🏻‍♂️s 53 times faster--73.6ms vs. 3.947s. 30 | 31 | The command keys are set to work more like they do on a mech ergo board. 32 | 33 | Currently, Home Row Mods work only one at a time, but hoping to get that sorted shortly. 🤓 34 | 35 | Karabiner still has some shortcomings. It seems like no matter how it's configured, typing rhythm isn't as natural with Karabiner as it is with [timeless Home Row Mods](https://github.com/urob/zmk-config#timeless-homerow-mods) in zmk using below config. 36 | 37 | ```dtsi 38 | hrml: home_row_mod_left { 39 | compatible = "zmk,behavior-hold-tap"; 40 | label = "HOME_ROW_MOD_LEFT"; 41 | #binding-cells = <2>; 42 | flavor = "balanced"; 43 | tapping-term-ms = ; 44 | hold-trigger-key-positions = < KEYS_R THUMBS >; 45 | hold-trigger-on-release; 46 | bindings = <&kp>, <&kp>; 47 | }; 48 | ``` 49 | 50 | 51 | ## Installing 52 | 53 | ### Karabiner.ts 54 | 55 | 1. Clone this repo. 56 | 2. cd to this subdirectory `cd engram/install/mac/karabiner`. 57 | 3. Create a profile in Karabiner called 'karabiner.ts'. 58 | 4. Run `deno task build` in the repo directory. 59 | 60 | ### Goku 61 | 62 | 1. Clone this repository. 63 | 2. cd to this subdirectory `cd engram/install/mac/karabiner`. 64 | 3. Create a profile in Karabiner called 'goku'. 65 | 4. Install Goku `brew install yqrashawn/goku/goku`. 66 | 5. From the repo directory, copy the config file to your `.config` directory `cp karabiner.edn ~/.config`. 67 | 6. Run Goku `goku` -------------------------------------------------------------------------------- /install/mac/karabiner/deno.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "build": "deno run -A index.ts" 4 | }, 5 | "importMap": "import_map.json", 6 | "fmt": { 7 | "semiColons": false, 8 | "singleQuote": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /install/mac/karabiner/engram.ts: -------------------------------------------------------------------------------- 1 | import { FromKeyParam, ModifierParam, ToKeyParam } from 'karabinerts' 2 | 3 | interface IEngram { 4 | from: FromKeyParam 5 | fromMod?: ModifierParam 6 | to: ToKeyParam 7 | toMod?: ModifierParam 8 | } 9 | 10 | const thumbs: IEngram[] = [ 11 | { from: '⇥', to: '⇥' }, 12 | { from: '␣', to: '␣' }, 13 | { from: '<⌘', to: '⌫' }, 14 | { from: '>⌘', to: '⏎' }, 15 | ] 16 | 17 | const left: IEngram[] = [ 18 | // Number Row 19 | { from: '`', to: '[' }, 20 | { from: 1, fromMod: '⇧', to: '\\', toMod: '⇧' }, 21 | { from: 2, fromMod: '⇧', to: '=' }, 22 | { from: 3, fromMod: '⇧', to: '`', toMod: '⇧' }, 23 | { from: 4, fromMod: '⇧', to: '=', toMod: '⇧' }, 24 | { from: 5, fromMod: '⇧', to: ',', toMod: '⇧' }, 25 | // Center Column/Punctuation 26 | { from: 't', fromMod: '⇧', to: '9', toMod: '⇧' }, 27 | { from: 't', to: 'quote' }, 28 | { from: 'g', fromMod: '⇧', to: ';' }, 29 | { from: 'g', to: 'comma' }, 30 | { from: 'b', to: '-' }, 31 | // Letters 32 | { from: 'q', to: 'b' }, 33 | { from: 'w', to: 'y' }, 34 | { from: 'e', to: 'o' }, 35 | { from: 'r', to: 'u' }, 36 | { from: 'a', to: 'c' }, 37 | { from: 's', to: 'i' }, 38 | { from: 'd', to: 'e' }, 39 | { from: 'f', to: 'a' }, 40 | { from: 'z', to: 'g' }, 41 | { from: 'x', to: 'x' }, 42 | { from: 'c', to: 'j' }, 43 | { from: 'v', to: 'k' }, 44 | ] 45 | 46 | const right: IEngram[] = [ 47 | // Number Row 48 | { from: 6, fromMod: '⇧', to: '.', toMod: '⇧' }, 49 | { from: 7, fromMod: '⇧', to: '6', toMod: '⇧' }, 50 | { from: 8, fromMod: '⇧', to: '7', toMod: '⇧' }, 51 | { from: 9, fromMod: '⇧', to: '5', toMod: '⇧' }, 52 | { from: 0, fromMod: '⇧', to: '8', toMod: '⇧' }, 53 | { from: '-', to: ']' }, 54 | { from: '=', fromMod: '⇧', to: '\\' }, 55 | { from: '=', to: '/' }, 56 | // Center Column/Punctuation 57 | { from: 'y', fromMod: '⇧', to: '0', toMod: '⇧' }, 58 | { from: 'y', to: '\'', toMod: '⇧' }, 59 | { from: 'h', fromMod: '⇧', to: ';', toMod: '⇧' }, 60 | { from: 'h', to: '.' }, 61 | { from: 'n', fromMod: '⇧', to: '1', toMod: '⇧' }, 62 | { from: 'n', to: '/', toMod: '⇧' }, 63 | { from: ']', fromMod: '⇧', to: '4', toMod: '⇧' }, 64 | { from: ']', to: '3', toMod: '⇧' }, 65 | { from: '\\', fromMod: '⇧', to: '`' }, 66 | { from: '\\', to: '2', toMod: '⇧' }, 67 | { from: '>⇧', fromMod: '⇧', to: '\\' }, 68 | { from: '>⇧', to: '/' }, 69 | // Letters 70 | { from: 'u', to: 'l' }, 71 | { from: 'i', to: 'd' }, 72 | { from: 'o', to: 'w' }, 73 | { from: 'p', to: 'v' }, 74 | { from: '[', to: 'z' }, 75 | { from: 'j', to: 'h' }, 76 | { from: 'k', to: 't' }, 77 | { from: 'l', to: 's' }, 78 | { from: ';', to: 'n' }, 79 | { from: '\'', to: 'q' }, 80 | { from: 'm', to: 'r' }, 81 | { from: ',', to: 'm' }, 82 | { from: '.', to: 'f' }, 83 | { from: '/', to: 'p' }, 84 | ] 85 | 86 | export const engram = [ 87 | ...left, 88 | ...right, 89 | ] 90 | 91 | export const engram_left = [...left, ...thumbs] 92 | export const engram_right = [...right, ...thumbs] 93 | -------------------------------------------------------------------------------- /install/mac/karabiner/import_map.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "karabinerts": "https://deno.land/x/karabinerts/deno.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /install/mac/karabiner/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | layer, 3 | map, 4 | rule, 5 | simlayer, 6 | // toKey, 7 | withMapper, 8 | withModifier, 9 | writeToProfile, 10 | } from 'karabinerts' 11 | import { engram, engram_left, engram_right } from './engram.ts' 12 | 13 | // writeToProfile("--dry-run", [ 14 | writeToProfile('karabiner.ts', [ 15 | layer('⇪', 'nav').manipulators([ 16 | withModifier('optionalAny')([ 17 | map('u').to('↖︎'), 18 | map('i').to('⇟'), 19 | map('o').to('⇞'), 20 | map('p').to('↘︎'), 21 | map('j').to('←'), 22 | map('k').to('↓'), 23 | map('l').to('↑'), 24 | map(';').to('→'), 25 | map('m').to('z', '<⌘'), 26 | map(',').to('x', '<⌘'), 27 | map('.').to('c', '<⌘'), 28 | map('/').to('v', '<⌘'), 29 | ]), 30 | ]), 31 | simlayer('f', '<⇧').manipulators([ 32 | // Reminder to experiment with .toDelayedAction() method 33 | // map('<⌘').toIfAlone('⌫').to('<⌘').toDelayedAction(toKey('m'), toKey('t')), 34 | // withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, "⌘⇧").condition(ifVar("<⌘", 1))), 35 | // withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, "⇧⌥").condition(ifVar("<⌥", 1))), 36 | // withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, "⌃⇧").condition(ifVar("<⌃", 1))), 37 | withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, '⇧')), 38 | ]), 39 | simlayer('j', '>⇧').manipulators([ 40 | // withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, "⌘⇧").condition(ifVar(">⌘", 1))), 41 | // withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, "⇧⌥").condition(ifVar(">⌥", 1))), 42 | // withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, "⌃⇧").condition(ifVar(">⌃", 1))), 43 | withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, '⇧')), 44 | ]), 45 | simlayer('d', '<⌘').manipulators([ 46 | // withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, "⌘⌥").condition(ifVar("<⌥", 1))), 47 | withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, '⌘')), 48 | ]), 49 | simlayer('k', '>⌘').manipulators([ 50 | // withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, "⌘⌥").condition(ifVar(">⌥", 1))), 51 | withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, '⌘')), 52 | ]), 53 | simlayer('s', '<⌥').manipulators([ 54 | withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, '⌥')), 55 | ]), 56 | simlayer('l', '>⌥').manipulators([ 57 | withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, '⌥')), 58 | ]), 59 | simlayer('a', '<⌃').manipulators([ 60 | withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, '⌃')), 61 | ]), 62 | simlayer(';', '>⌃').manipulators([ 63 | withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, '⌃')), 64 | ]), 65 | 66 | rule('short pinkies').manipulators([ 67 | withModifier('optionalAny')([ 68 | map('<⌘').toIfAlone('⌫').to('<⌘'), 69 | map('>⌘').toIfAlone('⏎').to('<⌘'), 70 | map('=').to('⌫'), 71 | map('>⇧', '<⇧').to('\\'), 72 | map('>⇧').to('/'), 73 | ]), 74 | ]), 75 | rule('engram').manipulators([ 76 | withModifier('optionalAny')([ 77 | withMapper(engram)((k) => map(k.from, k.fromMod).to(k.to, k.toMod)), 78 | ]), 79 | ]), 80 | ], { 81 | 'simlayer.threshold_milliseconds': 300, 82 | 'basic.to_delayed_action_delay_milliseconds': 251, 83 | 'basic.to_if_alone_timeout_milliseconds': 250, 84 | 'basic.to_if_held_down_threshold_milliseconds': 251, 85 | }) 86 | -------------------------------------------------------------------------------- /install/mac/karabiner/karabiner.edn: -------------------------------------------------------------------------------- 1 | ;; ORDER IS IMPORTANT! 2 | ;; This profile makes extensive use of the ## / optional any modifier. 3 | ;; Any shifted variants need to appear BEFORE the unshifted variant. 4 | ;; Karabiner will match the first rule it can. 5 | {:profiles 6 | {:Engram {:default true ;↓ delays can be set individually in mod-tap layer definitions if you want separate default values here 7 | :sim 50 ; | 50| simultaneous_threshold_milliseconds different from simlayers, this is for cases like [:a :b] 8 | :alone 209 ; |1000| to_if_alone_timeout_milliseconds ??? must be < than ↓:delay/:held to avoid the bug where mod-tap layer stays 1 9 | :held 210 ; | 500| to_if_held_down_threshold_milliseconds should = ↓:delay for mod-tap layers 10 | :delay 210 ; | | to_delayed_action_delay_milliseconds should = ↑:held for mod-tap layers 11 | ;; :default true 12 | ;; :sim 500 13 | ;; :delay 500 14 | ;; :alone 500 15 | ;; :held 200 16 | }} 17 | ;; :devices {:internal [{:vendor_id 1452 :product_id 641}]} 18 | :main [{:des "Nav and Clipboard" 19 | :rules [[:##caps_lock ["nac" 1] [:!symbols :!mouse :!shifted :!system] {:afterup ["nac" 0] :alone :escape}] 20 | :nac 21 | ;arrows 22 | [:##j :left_arrow] [:##k :down_arrow] [:##l :up_arrow] [:##semicolon :right_arrow] 23 | ; clipboard 24 | [:##z :!Cz] [:##x :!Cx] [:##c :!Cc] [:##v :!Cv]]} 25 | 26 | 27 | {:des " [⌂] mod-tap layers (asdf jkl;)" :rules [; When adding a new layer, if you want it to be able to cross with an old one, you must add the name negated (:!new_name) to all other mod-tap layer conditions 28 | ; remove these negations to allow mod key combos 29 | ; ⎇◆ (⌥⌘) sd and lkt 30 | ; ⇧⎇ sf and jl 31 | ; ⇧◆ (⇧⌘) fd and jk 32 | ; ⇧⎈ (⇧^) fa and jsc 33 | [:a nil [:!mode_s :!mode_d :!mode_j :!mode_k :!mode_l :!mod_sc] ;mode_a 34 | {:alone {:key :a :halt true} :delayed {:canceled {:key :a}} :held {:set ["mode_a" 1] :repeat false} :afterup {:set ["mode_a" 0]} 35 | :params {:alone 194 :held 195 :delay 195}}] 36 | [:s nil [:!mode_a :!mode_j :!mode_k :!mode_l :!mod_sc] ;mode_s 37 | {:alone {:key :s :halt true} :delayed {:canceled {:key :s}} :held {:set ["mode_s" 1] :repeat false} :afterup {:set ["mode_s" 0]} 38 | :params {:alone 194 :held 195 :delay 195}}] 39 | [:d nil [:!mode_a :!mode_j :!mode_k :!mode_l :!mod_sc] ;mode_d 40 | {:alone {:key :d :halt true} :delayed {:canceled {:key :d}} :held {:set ["mode_d" 1] :repeat false} :afterup {:set ["mode_d" 0]} 41 | :params {:alone 194 :held 195 :delay 195}}] 42 | [:f nil [:!mode_j :!mode_k :!mode_l :!mod_sc] ;mode_f 43 | {:alone {:key :f :halt true} :delayed {:canceled {:key :f}} :held {:set ["mode_f" 1] :repeat false} :afterup {:set ["mode_f" 0]} 44 | :params {:alone 194 :held 195 :delay 195}}] 45 | [:j nil [:!mode_a :!mode_s :!mode_d :!mode_f] ;mode_f 46 | {:alone {:key :j :halt true} :delayed {:canceled {:key :j}} :held {:set ["mode_j" 1] :repeat false} :afterup {:set ["mode_j" 0]} 47 | :params {:alone 194 :held 195 :delay 195}}] 48 | [:k nil [:!mode_a :!mode_s :!mode_d :!mode_f :!mod_sc] ;mode_k 49 | {:alone {:key :k :halt true} :delayed {:canceled {:key :k}} :held {:set ["mode_k" 1] :repeat false} :afterup {:set ["mode_k" 0]} 50 | :params {:alone 194 :held 195 :delay 195}}] 51 | [:l nil [:!mode_a :!mode_s :!mode_d :!mode_f :!mod_sc] ;mode_l 52 | {:alone {:key :l :halt true} :delayed {:canceled {:key :l}} :held {:set ["mode_l" 1] :repeat false} :afterup {:set ["mode_l" 0]} 53 | :params {:alone 194 :held 195 :delay 195}}] 54 | [:semicolon nil [:!mode_a :!mode_s :!mode_d :!mode_f :!mode_k :!mode_l] ;mod_sc 55 | {:alone {:key :semicolon :halt true} :delayed {:canceled {:key :semicolon}} :held {:set ["mod_sc" 1] :repeat false} :afterup {:set ["mod_sc" 0]} 56 | :params {:alone 194 :held 195 :delay 195}}]]} 57 | 58 | 59 | 60 | 61 | ;; {:des "Home Row Mods" 62 | :rules [; modifiers 63 | [:##a :left_control nil {:alone {:key :c} 64 | :sim {:key :c} 65 | 66 | ;; :delayed {:invoked {:key :c} :canceled {:key :c} } 67 | ;; :held {:key :left_control} 68 | }] 69 | [:##s :left_option nil {:alone {:key :i} 70 | :sim {:key :i} 71 | ;; :delayed {:invoked {:key :i} :canceled {:key :i}} 72 | ;; :held {:key :left_option} 73 | }] 74 | [:##d :left_command nil {:alone {:key :e} 75 | :sim {:key :e} 76 | ;; :delayed {:invoked {:key :e} :canceled {:key :e}} 77 | ;; :held {:key :left_command} 78 | }] 79 | [:##f :left_shift nil {:alone {:key :a} 80 | :sim {:key :a} 81 | ;; :delayed {:invoked {:key :a} :canceled {:key :a}} 82 | ;; :held {:key :left_shift} 83 | }] 84 | [:##j :left_shift nil {:alone {:key :h} 85 | :sim {:key :h} 86 | ;; :delayed {:canceled {:key :h}} 87 | ;; :held {:key :left_shift} 88 | }] 89 | [:##k :left_command nil {:alone {:key :t} 90 | :sim {:key :t} 91 | ;; :delayed { :canceled {:key :t}} 92 | ;; :held {:key :left_command} 93 | }] 94 | [:##l :left_option nil {:alone {:key :s} 95 | :sim {:key :s} 96 | ;; :delayed {:invoked {:key :s} :canceled {:key :s}} 97 | ;; :held {:key :left_option}}] 98 | }] 99 | [:##semicolon :left_control nil {:alone {:key :n} 100 | :sim {:key :n} 101 | ;; :delayed {:invoked {:key :n} :canceled {:key :n}} 102 | ;; :held {:key :left_control} 103 | }]]} 104 | 105 | 106 | {:des "Short Pinkies, Working Thumbs" 107 | :rules [;; Make Equal Sign Backspace so I don't have to reach so far, and change right shift to slash 108 | [:##left_command :left_command nil {:alone :delete_or_backspace}] 109 | [:##right_command :left_command nil {:alone :return_or_enter}] 110 | [:##equal_sign :delete_or_backspace] 111 | [:!S##right_shift :backslash] 112 | [:##right_shift :slash] 113 | [:##left_command :delete_or_backspace] 114 | [:##right_command :return_or_enter]]} 115 | {:des "Engram" 116 | :rules [;; Number Row 117 | [:##grave_accent_and_tilde :open_bracket] [:!S##1 :!Sbackslash] [:!S##2 :equal_sign] [:!S##3 :!Sgrave_accent_and_tilde] [:!S##4 :!Sequal_sign] [:!S##5 :!Scomma] [:!S##6 :!Speriod] [:!S##7 :!S6] [:!S##8 :!S7] [:!S##9 :!S5] [:!S##0 :!S8] [:##hyphen :close_bracket] [:!S##equal_sign :backslash] [:##equal_sign :slash] 118 | ;; Center Column/Punctuation 119 | [:!S##t :!S9] [:##t :quote] [:!S##y :!S0] [:##y :!Squote] 120 | [:!S##g :semicolon] [:##g :comma] [:!S##h :!Ssemicolon] [:##h :period] 121 | [:##b :hyphen] [:!S##n :!S1] [:##n :!Sslash] 122 | [:!S##close_bracket :!S4] [:##close_bracket :!S3] [:!S##backslash :grave_accent_and_tilde] [:##backslash :!S2] 123 | ;; Letters 124 | [:##q :b] [:##w :y] [:##e :o] [:##r :u] [:##u :l] [:##i :d] [:##o :w] [:##p :v] [:##open_bracket :z] 125 | [:##a :c] [:##s :i] [:##d :e] [:##f :a] [:##j :h] [:##k :t] [:##l :s] [:##semicolon :n] [:##quote :q] 126 | [:##z :g] [:##x :x] [:##c :j] [:##v :k] [:##m :r] [:##comma :m] [:##period :f] [:##slash :p]]}]} 127 | 128 | ;; ! | means mandatory 129 | ;; # | means optional 130 | ;; C | left_command 131 | ;; T | left_control 132 | ;; O | left_option 133 | ;; S | left_shift 134 | ;; F | fn 135 | ;; Q | right_command 136 | ;; W | right_control 137 | ;; E | right_option 138 | ;; R | right_shift 139 | ;; P | caps_lock 140 | ;; !! | mandatory command + control + optional + shift (hyper) 141 | ;; ## | optional any 142 | 143 | ;; examples 144 | 145 | ;; !CTSequal_sign | mandatory command control shift = 146 | ;; | which is command control + 147 | ;; !O#Sright_arrow | mandatory option optional any right_arrow 148 | 149 | -------------------------------------------------------------------------------- /install/mac/ukelele/Engram.bundle/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | org.sil.ukelele.keyboardlayout.engram2.0 7 | CFBundleName 8 | Engram 2.0 9 | CFBundleVersion 10 | 1.0 11 | KLInfo_Engram 12 | 13 | TICapsLockLanguageSwitchCapable 14 | 15 | TISInputSourceID 16 | org.sil.ukelele.keyboardlayout.engram2.0.engram 17 | TISIntendedLanguage 18 | en 19 | 20 | KLInfo_Engram – QWERTY ⌘ 21 | 22 | TICapsLockLanguageSwitchCapable 23 | 24 | TISInputSourceID 25 | org.sil.ukelele.keyboardlayout.engram2.0.engram–qwerty⌘ 26 | TISIntendedLanguage 27 | en 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /install/mac/ukelele/Engram.bundle/Contents/Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/mac/ukelele/Engram.bundle/Contents/Resources/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /install/mac/ukelele/Engram.bundle/Contents/version.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildVersion 6 | 1.0 7 | ProjectName 8 | Engram 2.0 9 | SourceVersion 10 | 1.0 11 | 12 | 13 | -------------------------------------------------------------------------------- /install/mac/ukelele/README.md: -------------------------------------------------------------------------------- 1 | Engram keyboard layout for Mac OSX 2 | =========== 3 | 4 | There are 2 layout options. 5 | * Engram - all inputs will use the Engram layout. 6 | * Engram + QWERTY ⌘ - all command shortcuts will use the QWERTY layout. 7 | 8 | ## Installation 9 | 10 | * Copy to a Keyboard Layouts directory: 11 | * Copying the bundle to /Library/Keyboard Layouts/ requires administrator rights to the computer, but will allow the layout system-wide, including the OS X login screen. To enable input options on the login window, check the option in System Preferences / Users & Groups / Login Options / Show Input menu in login window. 12 | * ~/Library/Keyboard Layouts/ needs less access and is specific to just the user’s account it is saved to. 13 | * Log out of OS X and log back in. 14 | * Open System Preferences, click on the Language & Text icon, and in the Input Menu tab enable the Engram layout. 15 | * Make sure that the Show input menu in menu bar box is also checked. 16 | 17 | ## Tools 18 | 19 | Ukelele to create the layout: 20 | http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=ukelele 21 | -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram/README.md: -------------------------------------------------------------------------------- 1 | ## Windows 2 | 3 | 1. Install the official _Microsoft Keyboard Layout Creator_ app: [MSKLC version 1.4]( 4 | https://www.microsoft.com/en-us/download/details.aspx?id=102134 5 | ). 6 | 7 | 2. Launch the MSKLC app and load the `engram.klc` keyboard layout source file: 8 | 9 | "C:\Program Files (x86)\Microsoft Keyboard Layout Creator 1.4\MSKLC.exe" engram.klc 10 | 11 | 3. Open the "Project" menu and select the "Build DLL and Setup Package" item. 12 | 13 | 4. Open the resulting build directory and run the `setup.exe` installer file. 14 | -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram/engram.klc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram/engram.klc -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/README.md: -------------------------------------------------------------------------------- 1 | # Engram Keyboard Layout Options for Windows 2 | 3 | - by Abigail Read (@AbbyRead), June 2022 4 | 5 | The available options contained in this zip file should, to the best of my knowledge, work on any Windows OS. 6 | ## Why not use the Keyman version instead? 7 | 8 | Keyman is great, but it necessitates an additional app running in the background (namely, Keyman) for it to work. This means if your computer runs an update or has a hiccup that causes it not to run at start-up you will have to open it up yourself manually before you can go back to using the layout. Kind of annoying. 9 | 10 | Additionally, and more importantly, Keyman seems to use some sort of higher level software trickery to do what it does. This means certain programs may not respond correctly to the layout. To get slightly technical as to why, when a program is designed within a framework meant to reach as many platforms as possible (Windows, Mac, Linux, etc.) it will often have things coded in a low-level way that acts as similarly as possible across multiple environments. Often the simplest route is the one with the least OS-specific best practices in mind. So when you have two programs functioning half right, where the Venn diagram overlaps is where it fails to deliver. 11 | 12 | So we end up back where we started, needing something that functions well on the operating system it was designed for. That's where these native ports come in. These were designed in Microsoft's own official app for doing so: Microsoft Keyboard Layout Creator, and the .klc files included here are the project files from that program. So, if you want to play around with them and make your own flavor, have at it. If you wish to publish that flavor though, have a look at the (very permissive) license here first: https://github.com/binarybottle/engram/blob/master/LICENSE 13 | 14 | ## Two versions? What's the difference? 15 | 16 | Inside the zip file, you will see two different folders: engram2b and engram2c. Most people will just want to go with engram2b, as that remains faithful to the Engram 2.0 layout. 17 | 18 | The other version is one Abby cooked up that rectifies (in a way) one very rare use case compatibility problem. On testing out the engram2b layout, my good friend Abby (the creator of this readme and port; I'm just going to talk in third-person) tried out DOSBox. Even with the layout correctly functioning as a Windows-compatible layout, was not recognised by DOSBox, presumably because it references hardware keys as opposed to whatever the operating system says a key is supposed to be. While this is bothersome for us, DOSBox at least has a key remapper program built-in and accessible during play. Where it falls short though is in assuming no one would ever want to reassign characters across different keys for when the shift key is or isn't held. So there is unfortunately NO KNOWN WAY for DOSBox to be made compatible with this layout short of going into the app's source code and doing it yourself. Abby's solution: Engram 2.C (for compatibility). This keeps most of the feel of the original intent, without splitting and reassigning the characters on any of the keys. So, keycap shape permitting, with the 2.C layout you could actually rearrange the real hardware keys yourself to get yourself an official unofficial Engram Keyboard, cheap as free! 19 | 20 | ## So why 2b? Why not just call it 2 if it's the same layout as 2.0? 21 | 22 | Well, Abby goofed on her first attempt, bless her heart. Ignoring all the validation warnings from the program, she spat out what we we'll now refer to as 2a, uploading it as fast as she could in order to get that sweet, sweet "I contributed to something" feel. In creating that version though she made some hasty assumptions as to what the operating system would do with its standard hotkeys. Turns out, Windows maintains the physical layout for things like cut, copy, paste WITHOUT needing to force it in the layout program (as she had tried to do with 2a). Forcing it (needlessly) by assigning just a BUNCH of exceptions for when Ctrl or Alt are pressed actually led to a buuuuuuuuuunch of compatibility hiccups. Hence why we do not speak of 2a. Only 2b (and maybe c). 23 | 24 | ## Installation 25 | 26 | When you decide on a layout or why-not-both it, you will need to run the setup.exe that will be found inside either folder. All this does is pick the appropriate .msi file for the processor your computer has and run it. If your computer doesn't trust it, try making it trust it. Tell him it'll be okay, just run it. should take like a millisecond to install, and you can thank your computer for bearing with you. 27 | 28 | ## Okay, where is it? 29 | 30 | On Windows 10: 31 | You should first try restarting your computer. Then go into Start --> Settings --> Time & Language --> Language (on the side pane). Scroll down to Preferred Languages, and you'll see English (I'm assuming). Click that, and then click Options. Scroll down to Keyboards and click Add a keyboard. Scroll through until you find one or more that start with "Engram 2.0". If you find one that just says Engram, don't click that; that's the Keyman version. I mean you can, but at this point, why you still bothering with that, huh? If you installed both, they may both show up as the exact same name. Abby don't know how to fix that. She put the name in the files right, but all she sees is twins on the OS. They still work like the two different versions though, b and c. Might just have to play around on notepad to determine which is which. Sorry. :shrug: 32 | 33 | ## But MAAAAAAAHM! I'm still having compatibility issues wif my favorite program!! 34 | 35 | Jeez, kid, get off my back. Haven't I done enough for you? Back in my day, we just had ONE layout, and it was QWERTY! If you want compatibility so bad why don't you go out and get a job! Earn your own compatibility for Christ's sake. 36 | 37 | But srsly this time. Autohotkey is amazing, and you should try figuring it out if you never want to have to use QWERTY again and maybe become a god in the process. Abby couldn't pull it off, but she's a hopeless goober. Don't be like Abby. Fail until you fail better. Fail upwards. Fake it until you make it more... more better. Being bad at something is the first step toward being kinda good at something. A cartoon for teeny child babies told me that one. I really like that cartoon. 38 | 39 | ## There any good places to practice this? 40 | 41 | A lot of places really. No need to buy Mavis Beacon anymore. All that paid stuff is waaaaaaay outdated at this point anyways. 42 | 43 | List of suggestions (in raw link form because Abigail is a lazy piece of work): 44 | https://monkeytype.com/ 45 | https://btype.io/ 46 | https://eatkin.itch.io/a-relaxing-typing-game 47 | https://www.tipp10.com/en/ 48 | https://klavaro.sourceforge.io/en/index.html 49 | https://www.gnu.org/savannah-checkouts/gnu/gtypist/gtypist.html 50 | 51 | ## Who can I thank for all this? 52 | 53 | Well, binarybottle mostly. He's the brains behind Engram 2.0, and Abby just copied his notes, made a port, a spinoff, and this weird readme that you definitely read all of just now. :wink: 54 | https://github.com/binarybottle 55 | https://github.com/AbbyRead 56 | 57 | ### Cheers! And happy typing! -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram v2B.klc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram v2B.klc -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2B.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2B.jpg -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2BShft.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2BShft.jpg -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2B_amd64.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2B_amd64.msi -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2B_i386.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2B_i386.msi -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2B_ia64.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/Engram2B_ia64.msi -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/amd64/Engram2B.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/amd64/Engram2B.dll -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/i386/Engram2B.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/i386/Engram2B.dll -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/ia64/Engram2B.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/ia64/Engram2B.dll -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/setup.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/setup.exe -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/wow64/Engram2B.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2b/wow64/Engram2B.dll -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram v2C.klc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram v2C.klc -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2C.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2C.jpg -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2CShft.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2CShft.jpg -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2C_amd64.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2C_amd64.msi -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2C_i386.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2C_i386.msi -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2C_ia64.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/Engram2C_ia64.msi -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/amd64/Engram2C.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/amd64/Engram2C.dll -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/i386/Engram2C.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/i386/Engram2C.dll -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/ia64/Engram2C.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/ia64/Engram2C.dll -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/setup.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/setup.exe -------------------------------------------------------------------------------- /install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/wow64/Engram2C.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/install/windows/microsoft_keyboard_layout_creator/engram_with_qwerty_hotkeys/engram2c/wow64/Engram2C.dll -------------------------------------------------------------------------------- /output/Factors24x24.txt: -------------------------------------------------------------------------------- 1 | [[0.9 0.91730769 0.95 0.94038462 0.531441 0.66871731 2 | 0.7695 0.84634615 0.34867844 0.39487088 0.5609655 0.76171154 3 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 4 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ] 5 | [0.82557692 0.93461538 0.96730769 0.95769231 0.82557692 0.55188104 6 | 0.70516731 0.95769231 0.48749492 0.36208915 0.41639424 0.69815769 7 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 8 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 9 | [0.855 0.87057692 1. 0.99038462 0.855 0.78351923 10 | 0.59049 0.99038462 0.623295 0.46266027 0.38742049 0.58481221 11 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 12 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 13 | [0.84634615 0.86192308 0.89134615 0.98076923 0.76171154 0.69815769 14 | 0.64979135 0.57913442 0.68554038 0.50895696 0.38369529 0.37997009 15 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 16 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 17 | [0.531441 0.91730769 0.95 0.84634615 0.9 0.91730769 18 | 0.95 0.94038462 0.531441 0.66871731 0.7695 0.84634615 19 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 20 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ] 21 | [0.60184558 0.55188104 0.87057692 0.77573077 0.82557692 0.93461538 22 | 0.96730769 0.95769231 0.82557692 0.55188104 0.70516731 0.95769231 23 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 24 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 25 | [0.69255 0.63465058 0.59049 0.72199038 0.855 0.87057692 26 | 1. 0.99038462 0.855 0.78351923 0.59049 0.99038462 27 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 28 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 29 | [0.76171154 0.86192308 0.89134615 0.57913442 0.84634615 0.86192308 30 | 0.89134615 0.98076923 0.76171154 0.69815769 0.64979135 0.57913442 31 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 32 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 33 | [0.34867844 0.54166102 0.69255 0.76171154 0.531441 0.91730769 34 | 0.95 0.84634615 0.9 0.91730769 0.95 0.94038462 35 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 36 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ] 37 | [0.35538379 0.36208915 0.51406697 0.56550773 0.60184558 0.55188104 38 | 0.87057692 0.77573077 0.82557692 0.93461538 0.96730769 0.95769231 39 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 40 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 41 | [0.50486895 0.37475482 0.38742049 0.4263281 0.69255 0.63465058 42 | 0.59049 0.72199038 0.855 0.87057692 1. 0.99038462 43 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 44 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 45 | [0.68554038 0.62834192 0.52633099 0.37997009 0.76171154 0.86192308 46 | 0.89134615 0.57913442 0.84634615 0.86192308 0.89134615 0.98076923 47 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 48 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 49 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 50 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 51 | 0.98076923 0.89134615 0.86192308 0.84634615 0.57913442 0.64979135 52 | 0.69815769 0.76171154 0.37997009 0.38369529 0.50895696 0.68554038] 53 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 54 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 55 | 0.99038462 1. 0.87057692 0.855 0.99038462 0.59049 56 | 0.78351923 0.855 0.58481221 0.38742049 0.46266027 0.623295 ] 57 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 58 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 59 | 0.95769231 0.96730769 0.93461538 0.82557692 0.95769231 0.70516731 60 | 0.55188104 0.82557692 0.69815769 0.41639424 0.36208915 0.48749492] 61 | [0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 62 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 63 | 0.94038462 0.95 0.91730769 0.9 0.84634615 0.7695 64 | 0.66871731 0.531441 0.76171154 0.5609655 0.39487088 0.34867844] 65 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 66 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 67 | 0.57913442 0.89134615 0.86192308 0.76171154 0.98076923 0.89134615 68 | 0.86192308 0.84634615 0.57913442 0.64979135 0.69815769 0.76171154] 69 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 70 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 71 | 0.72199038 0.59049 0.63465058 0.69255 0.99038462 1. 72 | 0.87057692 0.855 0.99038462 0.59049 0.78351923 0.855 ] 73 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 74 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 75 | 0.77573077 0.87057692 0.55188104 0.60184558 0.95769231 0.96730769 76 | 0.93461538 0.82557692 0.95769231 0.70516731 0.55188104 0.82557692] 77 | [0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 78 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 79 | 0.84634615 0.95 0.91730769 0.531441 0.94038462 0.95 80 | 0.91730769 0.9 0.84634615 0.7695 0.66871731 0.531441 ] 81 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 82 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 83 | 0.37997009 0.52633099 0.62834192 0.68554038 0.57913442 0.89134615 84 | 0.86192308 0.76171154 0.98076923 0.89134615 0.86192308 0.84634615] 85 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 86 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 87 | 0.4263281 0.38742049 0.37475482 0.50486895 0.72199038 0.59049 88 | 0.63465058 0.69255 0.99038462 1. 0.87057692 0.855 ] 89 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 90 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 91 | 0.56550773 0.51406697 0.36208915 0.35538379 0.77573077 0.87057692 92 | 0.55188104 0.60184558 0.95769231 0.96730769 0.93461538 0.82557692] 93 | [0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 94 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 95 | 0.76171154 0.69255 0.54166102 0.34867844 0.84634615 0.95 96 | 0.91730769 0.531441 0.94038462 0.95 0.91730769 0.9 ]] -------------------------------------------------------------------------------- /output/Factors24x24_heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Factors24x24_heatmap.png -------------------------------------------------------------------------------- /output/Factors24x24_histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Factors24x24_histogram.png -------------------------------------------------------------------------------- /output/Factors32x32.txt: -------------------------------------------------------------------------------- 1 | [[0.77966102 0.81779661 0.88983051 ... 0.78177966 0.70169492 0.70169492] 2 | [0.73601695 0.8559322 0.9279661 ... 0.81610169 0.73601695 0.73601695] 3 | [0.80084746 0.83516949 1. ... 0.8809322 0.80084746 0.80084746] 4 | ... 5 | [0.78177966 0.81610169 0.8809322 ... 0.77567797 0.56991737 0.63324153] 6 | [0.70169492 0.73601695 0.80084746 ... 0.56991737 0.63152542 0.37290945] 7 | [0.70169492 0.73601695 0.80084746 ... 0.63324153 0.37290945 0.63152542]] -------------------------------------------------------------------------------- /output/Factors32x32_heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Factors32x32_heatmap.png -------------------------------------------------------------------------------- /output/Factors32x32_histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Factors32x32_histogram.png -------------------------------------------------------------------------------- /output/Flow24x24_heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Flow24x24_heatmap.png -------------------------------------------------------------------------------- /output/Flow24x24_histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Flow24x24_histogram.png -------------------------------------------------------------------------------- /output/Flow32x32_heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Flow32x32_heatmap.png -------------------------------------------------------------------------------- /output/Flow32x32_histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Flow32x32_histogram.png -------------------------------------------------------------------------------- /output/Speed24x24_heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Speed24x24_heatmap.png -------------------------------------------------------------------------------- /output/Speed24x24_histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Speed24x24_histogram.png -------------------------------------------------------------------------------- /output/Speed32x32_heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Speed32x32_heatmap.png -------------------------------------------------------------------------------- /output/Strength24x24.txt: -------------------------------------------------------------------------------- 1 | [[0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 2 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 3 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 4 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ] 5 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 6 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 7 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 8 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 9 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 10 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 11 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 12 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 13 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 14 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 15 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 16 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 17 | [0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 18 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 19 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 20 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ] 21 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 22 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 23 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 24 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 25 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 26 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 27 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 28 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 29 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 30 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 31 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 32 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 33 | [0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 34 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 35 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 36 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ] 37 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 38 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 39 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 40 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 41 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 42 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 43 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 44 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 45 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 46 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 47 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 48 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 49 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 50 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 51 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 52 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 53 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 54 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 55 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 56 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 57 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 58 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 59 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 60 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 61 | [0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 62 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 63 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 64 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ] 65 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 66 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 67 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 68 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 69 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 70 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 71 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 72 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 73 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 74 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 75 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 76 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 77 | [0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 78 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 79 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 80 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ] 81 | [0.94038462 0.95769231 0.99038462 0.98076923 0.94038462 0.95769231 82 | 0.99038462 0.98076923 0.94038462 0.95769231 0.99038462 0.98076923 83 | 0.98076923 0.99038462 0.95769231 0.94038462 0.98076923 0.99038462 84 | 0.95769231 0.94038462 0.98076923 0.99038462 0.95769231 0.94038462] 85 | [0.95 0.96730769 1. 0.99038462 0.95 0.96730769 86 | 1. 0.99038462 0.95 0.96730769 1. 0.99038462 87 | 0.99038462 1. 0.96730769 0.95 0.99038462 1. 88 | 0.96730769 0.95 0.99038462 1. 0.96730769 0.95 ] 89 | [0.91730769 0.93461538 0.96730769 0.95769231 0.91730769 0.93461538 90 | 0.96730769 0.95769231 0.91730769 0.93461538 0.96730769 0.95769231 91 | 0.95769231 0.96730769 0.93461538 0.91730769 0.95769231 0.96730769 92 | 0.93461538 0.91730769 0.95769231 0.96730769 0.93461538 0.91730769] 93 | [0.9 0.91730769 0.95 0.94038462 0.9 0.91730769 94 | 0.95 0.94038462 0.9 0.91730769 0.95 0.94038462 95 | 0.94038462 0.95 0.91730769 0.9 0.94038462 0.95 96 | 0.91730769 0.9 0.94038462 0.95 0.91730769 0.9 ]] -------------------------------------------------------------------------------- /output/Strength24x24_heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Strength24x24_heatmap.png -------------------------------------------------------------------------------- /output/Strength24x24_histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Strength24x24_histogram.png -------------------------------------------------------------------------------- /output/Strength32x32.txt: -------------------------------------------------------------------------------- 1 | [[0.77966102 0.81779661 0.88983051 ... 0.86864407 0.77966102 0.77966102] 2 | [0.81779661 0.8559322 0.9279661 ... 0.90677966 0.81779661 0.81779661] 3 | [0.88983051 0.9279661 1. ... 0.97881356 0.88983051 0.88983051] 4 | ... 5 | [0.86864407 0.90677966 0.97881356 ... 0.95762712 0.86864407 0.86864407] 6 | [0.77966102 0.81779661 0.88983051 ... 0.86864407 0.77966102 0.77966102] 7 | [0.77966102 0.81779661 0.88983051 ... 0.86864407 0.77966102 0.77966102]] -------------------------------------------------------------------------------- /output/Strength32x32_heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Strength32x32_heatmap.png -------------------------------------------------------------------------------- /output/Strength32x32_histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binarybottle/engram-v2/8d87a46a91e738de94eb04887c9b209df9e15a72/output/Strength32x32_histogram.png -------------------------------------------------------------------------------- /output/onegram_frequencies.txt: -------------------------------------------------------------------------------- 1 | [0.12492063 0.09275565 0.08040605 0.07640693 0.07569278 0.07233629 2 | 0.06512767 0.06279421 0.05053301 0.04068986 0.03816958 0.03343774 3 | 0.02729702 0.02511761 0.02403123 0.02135891 0.01869376 0.01675664 4 | 0.0166498 0.01484649 0.01053252 0.00540513 0.00234857 0.00158774 5 | 0.00120469 0.00089951] --------------------------------------------------------------------------------