-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmarkov-chain-linearizer
executable file
·96 lines (69 loc) · 2.82 KB
/
markov-chain-linearizer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright © 2017 Martin Ueding <[email protected]>
import argparse
import os
import re
DIGITS_PATTERN = re.compile(r'(\d{3,4})')
def get_index(path):
basename = os.path.basename(path)
m = DIGITS_PATTERN.search(basename)
if m:
return int(m.group(1))
raise RuntimeError('The path `{}` did not contain a four digit number.'.format(path))
def extract_all_indices(paths):
return {
get_index(path): path
for path in paths
}
def get_new_path(path, new_dirname, new_index):
new_name = DIGITS_PATTERN.sub('{:04d}'.format(new_index), os.path.basename(path))
new_path = os.path.join(new_dirname, new_name)
return new_path
def main():
options = _parse_args()
forward = extract_all_indices(options.forward)
backward = extract_all_indices(options.backward)
# Get the index of the last backward element. This is going to be the very
# first element in the joined chain.
last = max(backward.keys())
new_midpoint = last - options.common
renames_forward = [
(new_midpoint + (index - options.common), path)
for index, path in sorted(forward.items())
]
renames_backward = [
(new_midpoint - (index - options.common), path)
for index, path in sorted(backward.items())
]
renames = renames_forward + renames_backward
mapping = [
(path, get_new_path(path, options.target, new_index))
for new_index, path in renames
]
if options.doit:
os.makedirs(options.target, exist_ok=True)
action = 'Symlinked' if options.doit else 'Would symlink'
for path, new_path in sorted(mapping):
print('{} {:30s} to {:30s}'.format(action, path, new_path))
if options.doit:
os.symlink(path, new_path)
if not options.doit:
print()
print('Run again with option `--doit` to actually create symlinks.')
def _parse_args():
'''
Parses the command line arguments.
:return: Namespace with arguments.
:rtype: Namespace
'''
parser = argparse.ArgumentParser(description='Linearizes two Markov chains into a single one with continous index numbers by creating symlinks.')
parser.add_argument('--forward', nargs='+', required=True, help='Paths to files from the forward chain')
parser.add_argument('--backward', nargs='+', required=True, help='Paths to files from the backward chain')
parser.add_argument('--common', type=int, required=True, help='Index which is common to both parts of the chain')
parser.add_argument('--target', required=True, help='Target directory for symlinks')
parser.add_argument('--doit', action='store_true', help='Actually create symlinks, otherwise a dry run is performed only')
options = parser.parse_args()
return options
if __name__ == '__main__':
main()