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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
from Numeric import sign
class PositionInWholeChain(object):
"""
"""
def __init__(self, wholechain, rail, index, direction):
self.wholechain = wholechain
self.rail = rail
self.index = index # base index in current rail
self.direction = direction # in current rail only
# note: our direction in each rail can differ.
self.off_end = False # might not be true, but if so we'll find out
# review: should we now move_by 0 to normalize index if out of range?
return
def move_by(self, relindex):
# don't i recall code similar to this somewhere? yes, BaseIterator.py - stub, not yet used
self.index += self.direction * relindex
self.off_end = False # be optimistic, we might be back on if we were off
assert 0 # LOGIC BUG: if rail dirs alternate as we move, then the following conds alternate too --
# we're not always in the same loop below!! (better find out if i need to write it this way
# or only as the scanner which yields the atoms -- might be easier that way) ### DECIDE
while self.index < 0 and not self.off_end:
self._move_to_prior_rail(sign(relindex))
while self.index >= len(self.rail) and not self.off_end:
self._move_to_next_rail(sign(relindex))
return
def _move_to_prior_rail(self, motion_direction):
assert self.index < 0 and not self.off_end
self._move_to_neighbor_rail(END0, motion_direction)# IMPORT, which variant of END0?
def _move_to_next_rail(self, motion_direction):
assert self.index >= len(self.rail) and not self.off_end
self._move_to_neighbor_rail(END1, motion_direction)
def _move_to_neighbor_rail(self, end, motion_direction):
neighbor_rail, index, direction = self.find_neighbor_rail(end) # IMPLEM
# index is on end we get onto first, direction is pointing into that rail,
# but does this correspond to our dir of motion or its inverse? depends on sign of relindex that got us here!
if not neighbor_rail:
self.off_end = True # self.index is negative but remains valid for self.rail
return
self.rail = neighbor_rail # now set index, direction to match
def yield_atom_posns(self, counter = 0, countby = 1, pos = None):
# maybe 1: might be a method on WholeChain which is passed rail, index, direction, then dispense with this object,
# OR, maybe 2: might yield a stream of objects of this type, instead
grab the vars
if pos is None: # if pos passed, self is useless -- so use WholeChain method which is always passed pos; in here, no pos arg
pos = self.pos
while 1: # or, while not hitting end condition, like hitting start posn again
if direction > 0:
while index < len(rail):
yield rail, index, direction # and counter?
index += 1
now jump into next rail, no data needed except jump off END1 of this rail
else:
while index >= 0:
yield rail, index, direction # and counter?
index -= 1
now jump off END0 of this rail, and continue
this might be correct:
class PositionInWholeChain(object):
"""
"""
def __init__(self, wholechain, rail, index, direction):
self.wholechain = wholechain
self.rail = rail
self.index = index # base index in current rail
self.direction = direction # in current rail only
# note: our direction in each rail can differ.
self.pos = (rail, index, direction) ##k or use property for one or the other?
return
def yield_rail_index_direction_counter(self, **options):
return self.wholechain.yield_rail_index_direction_counter( self.pos, **options )
def _that_method_in_WholeChain(self, pos, counter = 0, countby = 1):
"""
@note: the first position we yield is always pos, with the initial value of counter.
"""
rail, index, direction = pos
# assert one of our rails, valid index in it
assert direction in (-1, 1)
while 1:
# yield, move, adjust, check, continue
yield rail, index, direction, counter
# move
counter += countby
index += direction
# adjust
def jump_off(end):
neighbor_atom = rail.neighbor_baseatoms[end]
# neighbor_atom might be None, atom, or -1 if not yet set
assert neighbor_atom != -1
if neighbor_atom is None:
rail = None # outer code will return due to this
index, direction = None, None # illegal values (to detect bugs in outer code)
else:
rail, index, direction = self._find_end_atom_chain_and_index(neighbor_atom)
assert rail
return rail, index, direction
if index < 0:
# jump off END0 of this rail
rail, index, direction = jump_off(LADDER_END0)
elif index >= len(rail):
# jump off END1 of this rail
rail, index, direction = jump_off(LADDER_END1)
else:
pass
# check
if not rail:
return
assert 0 <= index < len(rail)
assert direction in (-1, 1)
} # TODO: or if reached starting pos or passed ending pos, return
continue
assert 0 # not reached
pass
|