I have multiple functions. One function (estimation) calls on the variables of the other(callback) in order to perform a calculation. However, there are a couple of issues.
It seems like the variables aren't getting passed, and ...
It seems like the function(estimation) never gets called to run, and I don't know why.
What I want is to have the estimate result print out, but nothing is being printed.
If someone could let me know what I'm doing wrong I'd appreciate it.
EX:
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
import math
from geometry_msgs.msg import Quaternion
from sensor_msgs.msg import Imu
import numpy as np
from rclpy.qos import qos_profile_sensor_data
class S_E(Node):
def __init__(self):
super().__init__('s_e')
self.sub = self.create_subscription(Imu, '/imu', self.callback, qos_profile=qos_profile_sensor_data)
def callback(self, msg):
quat = self.quat = msg.orientation # x,y,z
a_rate = self.a_rate = msg.angular_velocity # x,y,z
return quat, a_rate
def estimation(self):
print("Hello")
quat, a_rate = callback()
estimate = (0.5 * a_rate) * quat
print(estimate)
def main(args=None):
rclpy.init(args=args) # initialize ROS2 Library
s_e = S_E() # make an object of class
try:
while (1):
rclpy.spin(s_e)
except Exception as e:
print("Exception: {}".format(e))
rclpy.spin(s_e)
rclpy.shutdown()
if __name__ == '__main__':
main()
You are not calling the estimation function on your object. You would do that by doing something like this
s_e = S_E()
s_e.estimation()
Related
I am trying to use Python unittest library to test the following code.
from cv2 import imwrite
import h5py
import lumpy as np
class Myclass:
def __init__(self):
self.data = []
def get_data(self):
return self.data
def load_data(self, path):
count = 10
for i in range(count):
mat_file = path + f'{i}.mat'
with h5py.File(mat_file, 'r') as fin:
data = np.array(fin['data'])
for j in range(len(data)):
filename = path + f'{i}_{j}.jpg'
imwrite(filename, data)
self.data = data
I tried to do the following. But I am getting AttributeError saying Myclass has no attribute 'imwrite'. And I do not know how to mock the nested loops with image writing imwrite.
from mock import MagicMock, patch
def test():
m = MagicMock()
m.__enter__.return_value = data
with patch("h5py.File", return_value=m):
with patch(Myclass.imwrite) as mock_imwrite:
testclass = Myclass()
testclass.load_data(path='test')
assert testclass.get_data() == data
I hope someone can help me out. Any help is very much appreciated
The issue here is that your class Myclass does not have a function imwrite. Only the module (aka the file the class is defined in) is aware of this function.
If you want to patch the imwrite function of the package cv2, you have to write:
(untested code)
with patch('cv2.imwrite') as mock_imwrite:
testclass = Myclass()
...
But the as mock_imwrite part is only needed, if you run an assert on the mock. Otherwise, you may just skip it.
EDIT
This short code below triggers the same issue.
# top_level.py
import to_import
if __name__ == '__main__':
# This does not work
t = to_import.Test()
from pprint import pprint
pprint(t.test())
#to_import.py
import multiprocessing as mp
def test_func(a, b):
return a * b
class Test:
def __init__(self):
self.pairs = list()
for i in range(10):
for j in range(10):
self.pairs.append((i, j))
def test(self):
pairs = tuple(self.pairs)
with mp.Pool() as pool:
results = pool.starmap(test_func, pairs)
return results
if __name__ == '__main__':
# This works fine
t = Test()
from pprint import pprint
pprint(t.test())
END EDIT
DOUBLE EDIT
Interestingly, this code works correctly when run from my command prompt, as opposed to how I'd been running it from within Spyder previously
EDIT END
I have a class Tin which stores a 3d surface as a series of points and triangles, and can generate a regular grid of points on that surface. The process of creating these points works fine when the multiprocessing flag is False.
However for very dense grids on large surfaces this process can be quite slow, so I implemented multiprocessing to speed it up.
# tin.py
from time import time
import multiprocessing as mp
def _points_from_face(points, grid_size):
create 3d points within triangle on grid, uses other functions withinin this module
def _multiprocess_function(function, vals_gen, pool_size):
with mp.Pool(processes=pool_size) as pool:
results = pool.starmap(func=function,
iterable=vals_gen)
return results
class Tin:
def __init__(self, name, surface_dict):
self.name = name
self.points = surface_dict['Points']
self.faces = dict(enumerate(surface_dict['Faces']))
def generate_regular_grid(self, grid_size,
multiprocess=False,
pool_size=(mp.cpu_count()//2)):
return_grid = dict()
if pool_size < 1:
multiprocess = False
if multiprocess:
faces_tuple = tuple(self.faces.values())
vals_tuple = tuple((tuple(self.points[pid] for pid in face), grid_size)
for face in faces_tuple)
results = _multiprocess_function(_points_from_face,
vals_tuple,
pool_size)
for result in results:
return_grid.update(result)
else:
for face in self.faces.values():
points = tuple(self.points[pid] for pid in face)
return_grid.update(_points_from_face(points, grid_size))
return return_grid
When the Tin class and associated functions are in the same python file as the code calling them, the script works fine, the processes spin up, do their thing, and then close.
But when I import tin.py into another script and try to use multiprocessing, the program gets stuck creating and killing processes over and over without returning anything.
e.g.
# landxml.py
from time import time
from tin import Tin
def parse_landxml(xml_path: str, print_times=False) -> Tin:
read xml file and return Tin contained within
if __name__ == '__main__':
st = time()
surface = parse_landxml('some_tin.xml',
print_times=True)
grid = surface.generate_regular_grid(grid_size=2,
print_times=True,
multiprocess=True)
Do I need to keep everything in one long script or is there a way I can still use multiprocessing inside an imported script.
In addition landxml.py will be imported into another file itself, is this likely to cause the same problem again?
I'm studying the MVP pattern but having a hard time following the principles in order to update in real time a progress bar. As I understand the Presenter checks if there's any update in the Model and then outputs the result, so there's no instantiation of the Presenter in the Model, only the Presenter should instantiate the Model and the View.
My question is: how should I update the progress bar by following the MVP principle?
I could of course call presenter.update_progress_bar(i, total) from Model, but then it would infringe the MVP principle.
Here's a minimal working example:
PS: for now, I'm using CLI.
/main.py
import modules
def main():
modules.View(modules.Presenter).run()
if __name__ == "__main__":
main()
/modules/__init__.py
from modules.Model.Model import Model
from modules.Model.progressbar import ProgressBar
from modules.View.View import View
from modules.Presenter.Presenter import Presenter
/modules/Model/Model.py
class Model:
def __init__(self):
pass
def long_process(self):
import time
for i in range(10):
time.sleep(0.1)
print("Update the progress bar.")
return True
/modules/Model/progressbar.py
# MIT license: https://gist.github.com/vladignatyev/06860ec2040cb497f0f3
import sys
class ProgressBar:
def progress(count, total, status=''):
bar_len = 60
filled_len = int(round(bar_len * count / float(total)))
percents = round(100.0 * count / float(total), 1)
bar = '=' * filled_len + '-' * (bar_len - filled_len)
sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percents, '%', status))
sys.stdout.flush()
/modules/View/View.py
import sys
class View:
def __init__(self, presenter):
self.presenter = presenter(self)
def run(self):
self.presenter.long_process()
def update_progress_bar(self, msg):
sys.stdout.write(msg)
def hide_progress_bar(self, msg):
sys.stdout.write(msg)
def update_status(self, msg):
print(msg)
/modules/Presenter/Presenter.py
class Presenter:
def __init__(self, view):
import modules
self.model = modules.Model()
self.view = view
def long_process(self):
if self.model.long_process():
self.view.update_status('Long process finished correctly')
else:
self.view.update_status('error')
def update_progress_bar(self, i, total):
from modules import ProgressBar
ProgressBar.progress(i, total)
self.view.update_progress_bar(ProgressBar.progress(i, total))
def end_progress_bar(self):
self.view.end_progress_bar('\n')
I could do:
class Model:
def __init__(self, presenter):
self.presenter = presenter # Violation of MVP
def long_process(self):
import time
for i in range(10):
time.sleep(0.1)
self.presenter.update_progress_bar(i, 10) # Violation of MVP
print("Update the progress bar.")
return True
But this is wrong since the Model now instantiates the Presenter. Any suggestions?
Use a callback:
import time
class Model:
def long_process(self, notify=lambda current, total: None):
for i in range(10):
time.sleep(0.1)
notify(i, 10)
return True
class Presenter:
def long_process(self):
result = self.model.long_process(lambda c, t: self.update_progress_bar(c, t)):
if result:
self.view.update_status('Long process finished correctly')
else:
self.view.update_status('error')
This keeps your model independant from the client code, while still allowing it (the model I mean) to notify it's caller.
As a side note, there are quite a few things in your code that are totally unpythonic:
1/ you don't have to put each class in a distinct module (it's actually considered an antipattern in Python), and even less in nested submodules (Python Zen: "flat is better than nested").
2/ you don't have to use classes when a plain function is enough (hint: Python functions are objects... actually, everything in Python is an object) - your ProgressBar class has no state and only one method, so it could just be a plain function (Python Zen: "simple is better than complex").
3/ imports should be at the top of the module, not in functions (if you have to put them in a function to solve cyclic dependancies issues then the proper solution is to rethink your design to avoid cyclic dependancies).
4/ module names should be all_lower
I have a some bunch of python files. I need to get all the classes from there and make a list.
its like I have to read with streamreader and then
Imports ActionBlock
I have to take the string ActionBlock and show it in a list. Listing and others hopefully I can do, but I am stuck in this point. Any suggestion please? Thank you.
You could use a regular expression to look for the parts you're interested in.
The following code
Dim path = "c:\path\to\your\file.py"
Dim content = File.ReadAllText(path)
Dim matchClass = "class (?<m>\w+)(:|\()+"
Dim matchImport = "(^|from \w+ )import ((?<m>\w+), )*(?<m>\w+)"
Dim result = Regex.Matches(content, String.Format("({0}|{1})", matchClass, matchImport), RegexOptions.Multiline) _
.Cast(Of Match) _
.SelectMany(Function(m) m.Groups("m").Captures.Cast(Of Capture).Select(Function(c) c.Value)) _
.ToList()
will, given a text file like
import os
import math
from time import clock
from random import randint
import DataArchiving
import TABasicFunctions
import HWDataConveterGate
import GeneralTestDataMapping
from something import FirstClass, SecondClass
def foo():
pass
def bar():
pass
class ClassOne(object):
class NestedClass:
pass
def thisisnotaclass(self):
v = [x.class for x in self]
v = [x.someimport for x in self]
class ClassTwo:
pass
class Class3:
pass
def main():
pass
if __name__ == '__main__':
main()
create a list that looks like:
I have a simple program that gets an text input from the user, and displays it on an instrument (Keithley). However, the attribute does not seem to change. That is, when I run the Start method, the output is "Wowee", even if I change Display in a pop-up window. Do I have to make it editable? I didn't think so. I am basically following Gael Varoquaux's intro to traits.
COntrolPanel.py:
from traits.api import *
from traitsui.api import *
import Keithley3706A_module
class ControlPanel(HasTraits):
keithley2430settings = Instance(Keithley2430.Keithley2430Settings, ())
keithley3706Asettings = Instance(Keithley3706A_module.Keithley3706ASettings, ())
start = Button("Start Measurements")
clear_3706A_display = Button("Clear K3706A Display")
k3706A_settings = Keithley3706A_module.Keithley3706ASettings()
k3706A = Keithley3706A_module.Keithley3706A()
view = View(Item('start', show_label=False,style='custom' ),
Item('clear_3706A_display', show_label=False,style='custom' ),
Item('keithley2430settings',style='custom'),
Item('keithley3706Asettings',style='simple'))
def _start_fired(self):
print "hello %s" % self.k3706A_settings.display
self.k3706A.message(self.k3706A_settings.display)
def _clear_3706A_display_fired(self):
self.k3706A.clear()
if __name__ == '__main__':
ControlPanel().configure_traits()
Keithley3706A.py:
from traits.api import *
from traitsui.api import *
import visa
import time
class Keithley3706ASettings(HasTraits):
display = String("Wowee")
class Keithley3706A(HasTraits):
def __init__(self):
self.Keithley3706AUSB = visa.instrument("USB0::0x05E6::0x3706::04019447::INSTR")
def message(self,foo):
s="display.settext('%s')" % foo
self.Keithley3706AUSB.write("display.clear()")
self.Keithley3706AUSB.write(s)
def clear(self):
self.Keithley3706AUSB.write("display.clear()")
In the ControlPanel class, you have created two different instances of Keithley3706ASettings, namely keithley3706Asettings and k3706A_settings. If I delete the latter, and replace the use of k3706A_settings with keithley3706Asettings, it works. Here's my version (with references to the 2430 device removed, the k3706A trait declared as an Instance of Keithley3706A, and a few other irrelevant UI changes):
class ControlPanel(HasTraits):
keithley3706Asettings = Instance(Keithley3706A_module.Keithley3706ASettings, ())
k3706A = Instance(Keithley3706A_module.Keithley3706A, ())
start = Button("Start Measurements")
clear_3706A_display = Button("Clear K3706A Display")
view = View(UItem('start'),
UItem('clear_3706A_display'),
Item('keithley3706Asettings', style='simple'))
def _start_fired(self):
print "hello %s" % self.keithley3706Asettings.display
self.k3706A.message(self.keithley3706Asettings.display)
def _clear_3706A_display_fired(self):
self.k3706A.clear()