'Problem with using numpy.float32 value in if clause
I have a simple test application for GNUradio where I try top convert a input in range -180...180 to range 0...360. I've written python code and QA code for that, but cannot seem to get the if-else statements to work properly.
The problem seems to be that the if clause only sees the first element of the test src_data vector because I use input_elements[0][0]. I tried using input_elements[0], but in that case I get and error about comparing array to integer. How to solve this problem?
The block in python is as follows:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2018 <+YOU OR YOUR COMPANY+>.
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
import numpy
from gnuradio import gr
class convert_ff(gr.sync_block):
"""
docstring for block convert_ff
"""
def __init__(self):
gr.sync_block.__init__(self,
name="convert_ff",
in_sig=[numpy.float32],
out_sig=[numpy.float32])
def work(self, input_items, output_items):
print input_items[:][0]
out = output_items[0]
if input_items[0][0] < 0:
out[:]=360+input_items[0]
print "negative value processed"
else:
out[:]=input_items[0]
return len(output_items[0])
And the QA code is as follows:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2018 <+YOU OR YOUR COMPANY+>.
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
from gnuradio import gr, gr_unittest
from gnuradio import blocks
from convert_ff import convert_ff
class qa_convert_ff (gr_unittest.TestCase):
def setUp (self):
self.tb = gr.top_block ()
def tearDown (self):
self.tb = None
def test_001_t (self):
src_data = (20,90,180,280,-20,-90,-190)
print "This is source data"
print src_data
expected_result = (20,90,180,280,340,270,170)
src=blocks.vector_source_f(src_data)
convert=convert_ff()
snk=blocks.vector_sink_f()
self.tb.connect(src,convert)
self.tb.connect(convert,snk)
self.tb.run ()
# check data
self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6)
if __name__ == '__main__':
gr_unittest.run(qa_convert_ff, "qa_convert_ff.xml")
Solution 1:[1]
Generally to extend an "if" statement to a numpy.array, the best solution is to use a mask which is obtained for instance by comparing an array to an integer (or to another array of the same size):
mask = input_items[0] < 0
the mask is an boolean array of the same dimension. Then, you can act only on a selection of your array using the mask:
out[mask] = 360+input_items[mask]
numpy.logical_not() is a fast way to obtain the not mask:
out[numpy.logical_not(mask)] = input_items[numpy.logical_not(mask)]
So your work function should be:
def work(self, input_items, output_items):
print input_items[:][0]
out = output_items[0]
mask = input_items[0] < 0
out[mask] = 360+input_items[mask]
out[numpy.logical_not(mask)] = input_items[numpy.logical_not(mask)]
return len(output_items[0])
you can do even shorter, not storing the mask:
def work(self, input_items, output_items):
out = input_items[0].copy()
out[out < 0] += 360.
return out
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |