Issue
I am using the code below to detect transitions from False to True. I need separate code that only detects changes from True to False. Is there a way to do this with the current code below?
test = [True, False, False, True, True, False, True, True, False, False, False, True]
class EdgeDetector:
"""Detects False to True transitions on an external signal."""
def __init__(self, reader, action):
self.reader = reader
self.action = action
self.last_value = reader() # initialise value
def test(self):
new_value = self.reader()
if new_value and not self.last_value:
self.action()
self.last_value = new_value
# simple self-test
if __name__ == '__main__':
vlist = test
vgen = (v for v in vlist) # generator for value sequence
def test_reader(): # generate test sequence
value = next(vgen)
print("Read:", value)
return value
def printer():
print("Phase transition")
test_subject = EdgeDetector(test_reader, printer)
for i in range(len(vlist)-1):
test_subject.test()
Note: This is not my code. I am using the code provided from this thread: How to execute a function once when boolean value changes in python?
I can't post in that thread to ask a follow up question. Any assistance is appreciated.
Solution
The problem is here if new_value and not self.last_value:
So the first part is looking for if new_value has a Truthy value. AND it's looking for if self.last_value has a Falsey value. This gets muddy when you start comparing two different booleans to each other.
The first part is really looking to see if there is a value in new_value. So we can instead compare it to none. The second part is really looking to see if the two booleans match, so we can just compare them to each other.
Update the line to this, and it should work for transitions in either direction.
if new_value is not None and new_value is not self.last_value:
Edit:
As per your comments: There are a couple ways we can track what the phase transitions are with out having to look up each one.
Option One:
Using one function to track both transition to false from true and to true from false. We can pass the value back to the printer function.
def test(self):
new_value = self.reader()
if new_value is not None and new_value is not self.last_value:
self.action(new_value) # Note here we are passing a value back
self.last_value = new_value
Now we just add to the printer function to see the changes.
def printer(transition):
print(f"Phase transition to: {transition}")
Finalized Code Option 1:
test = [True, False, False, True, True, False, True, True, False, False, False, True]
class EdgeDetector:
"""Detects False to True transitions on an external signal."""
def __init__(self, reader, action):
self.reader = reader
self.action = action
self.last_value = reader() # initialize value
def test(self):
new_value = self.reader()
if new_value is not None and new_value is not self.last_value:
self.action(new_value)
self.last_value = new_value
# simple self-test
if __name__ == '__main__':
vlist = test
vgen = (v for v in vlist) # generator for value sequence
def test_reader(): # generate test sequence
value = next(vgen)
print("Read:", value)
return value
def printer(transition):
print(f"Phase transition to: {transition}")
test_subject = EdgeDetector(test_reader, printer)
for i in range(len(vlist)-1):
test_subject.test()
Option Two:
This is the way to do it if you want separate code for transitions from false to true and for from true to false.
First in the EdgeDetector class we need to modify the init as so:
def __init__(self, reader, action_true, action_false): #Note the second action here
self.reader = reader
self.action_true = action_true
self.action_false = action_false # We set it just like the previous one.
self.last_value = reader()
Then we can update the test code.
def test(self):
new_value = self.reader()
if new_value is not None and new_value is not self.last_value:
if new_value:
self.action_true()
else:
self.action_false()
self.last_value = new_value
Then we modify the printer statement and add a second one:
def printer_true():
print("Phase transition to true")
def printer_false():
print("Phase transition to false")
Finally the initialization of EdgeDetector needs to be updated.
test_subject = EdgeDetector(test_reader, printer_true, printer_false)
Finalized Code for Option 2
test = [True, False, False, True, True, False, True, True, False, False, False, True]
class EdgeDetector:
"""Detects False to True transitions on an external signal."""
def __init__(self, reader, action_true, action_false):
self.reader = reader
self.action_true = action_true
self.action_false = action_false
self.last_value = reader() # initialize value
def test(self):
new_value = self.reader()
if new_value is not None and new_value is not self.last_value:
self.action(new_value)
self.last_value = new_value
# simple self-test
if __name__ == '__main__':
vlist = test
vgen = (v for v in vlist) # generator for value sequence
def test_reader(): # generate test sequence
value = next(vgen)
print("Read:", value)
return value
def printer_true():
print(f"Phase transition to true")
def printer_false():
print(f"Phase transition to false")
test_subject = EdgeDetector(test_reader, printer_true, printer_false)
for i in range(len(vlist)-1):
test_subject.test()
Answered By - Rashid 'Lee' Ibrahim
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.