## Python equivalent of map function in Arduino

nautilus27
Posts: 72
Joined: Fri May 22, 2015 9:38 pm

### Python equivalent of map function in Arduino

Since I mostly work with Arduinos, I'm very new to Python and would like to know if there are any functions in Python that takes minimum and maximum values of a float and convert it to another range of values. I know map doesn't do float but you get the point.

For instance my analog thumbstick reports "-1.0" on left "1.0" on right. It reports values like " 0.46537373737" in between those. And I need convert this to an integer with the minimum value of 0 and maximum value of 10. How can I do this in Python?

DougieLawson
Posts: 37653
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK

### Re: Python equivalent of map function in Arduino

For your example this code works

Code: Select all

``int_val = int(round(float_val * 10))``
Note: Any requirement to use a crystal ball or mind reading will result in me ignoring your question.

All non-medical doctors are on my foes list.

Massi
Posts: 1691
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

### Re: Python equivalent of map function in Arduino

DougieLawson wrote:For your example this code works

Code: Select all

``int_val = int(round(float_val * 10))``
if it has to be 0-10 for the whole interval, you should multiply by 5 (scale) and then sum 5 (translate)

like

Code: Select all

``int_val = int(float_val * 5 + 5)``
isn't "round" covered implicitly by "int"?

PiGraham
Posts: 3780
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

### Re: Python equivalent of map function in Arduino

The Arduino docs give the function definition, if you can't work it out:

Code: Select all

``````long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

``````

PiGraham
Posts: 3780
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

### Re: Python equivalent of map function in Arduino

Massi wrote:
DougieLawson wrote:For your example this code works

Code: Select all

``int_val = int(round(float_val * 10))``
if it has to be 0-10 for the whole interval, you should multiply by 5 (scale) and then sum 5 (translate)

like

Code: Select all

``int_val = int(float_val * 5 + 5)``
isn't "round" covered implicitly by "int"?
That will do it. Or the equivalent :

Code: Select all

``int_val = int((float_val + 1.0) * 10)``

scruss
Posts: 2895
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

### Re: Python equivalent of map function in Arduino

Wiring/Arduino inherited the map() function from Processing. The old code from the processing PApplet.java looks like this:

Code: Select all

``````  static public final double map(double value,
double istart, double istop,
double ostart, double ostop) {
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
``````
(I linked to the simpler old code, as the new code involves some exception handling in Java that is too long for here)

This would translate into Python as something like:

Code: Select all

``````def valmap(value, istart, istop, ostart, ostop):
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))

print '%-8s %-6s' % ('Input', 'Output')
for x in range(21):
inval = float((x - 10) / 10.0)
print '%8.3f %6.1f' % (inval, valmap(inval, -1.0, 1.0, 0.0, 10.0))
``````
I used the name valmap, as map() is already a built-in function that does something completely different.

NB: I know you asked for integer results, but I kept as close to the original Processing floating-point function.
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.

MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

### Re: Python equivalent of map function in Arduino

So, based on the OPs question, and the maths from the gang, the solution is to create a python function called map() that does precisely what the OP requires (and it takes in floats, and gives back ints).

pMapTest.py

Code: Select all

``````def map(x, in_min, in_max, out_min, out_max):
return int((x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min)
``````
run it...

Code: Select all

``````>>> from pMapTest import *
>>> map(.496, -1, 1, 0, 10)
7
>>> map(-1, -1, 1, 0, 10)
0
>>> map(1, -1, 1, 0, 10)
10
>>>
>>>
``````
marcus

Massi
Posts: 1691
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

### Re: Python equivalent of map function in Arduino

MarkHaysHarris777 wrote:So, based on the OPs question, and the maths from the gang, the solution is to create a python function called map() that does precisely what the OP requires (and it takes in floats, and gives back ints).
definitely no.

https://docs.python.org/2/library/functions.html#map

(as said above)

MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

### Re: Python equivalent of map function in Arduino

Massi wrote:
MarkHaysHarris777 wrote:So, based on the OPs question, and the maths from the gang, the solution is to create a python function called map() that does precisely what the OP requires (and it takes in floats, and gives back ints).
definitely no.

https://docs.python.org/2/library/functions.html#map

(as said above)
Nope... incorrect paradigm ! Think out of the box. We're importing a special case that we only need to import for this one app. It depends on whether your app needs the built-in, and whether any of the imported cruft in the app also needs the built-in.

But, call it whatever you want to! The name is not important; its what it does that matters... a rose is a rose by any other name...

here:

Code: Select all

``````def my_map(x, in_min, in_max, out_min, out_max):
return int((x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min)
``````
edit: ... and another thing, the fact that Python uses namespace(s) allows us to create all kinds of
map() functions by the same name, because we are going to import them into a different namespace. This is an important Python concept; a part of the zen of Python: to wit-- near the bottom:

Code: Select all

``````>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>>
``````
marcus

scruss
Posts: 2895
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

### Re: Python equivalent of map function in Arduino

MarkHaysHarris777 wrote:allows us to create all kinds of
map() functions by the same name
So you can silently overwrite builtins? There's no way this will end badly …
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.

MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

### Re: Python equivalent of map function in Arduino

scruss wrote:
MarkHaysHarris777 wrote:allows us to create all kinds of
map() functions by the same name
So you can silently overwrite builtins? There's no way this will end badly …
No, no, no... not at all... you qualify the names into the namespaces where you'll be using them. For instance the map() function I wrote would be part of a module called (maybe) my_translations.py and would be pulled in with:

Code: Select all

``````import my_translations as XLATE
``````
Then, I would use the map function like this:

Code: Select all

``````XLATE.map(.469, -1, 1, 0, 10)
``````
This is no different than how you use the RPi.GPIO module; or any other module. Each module is free to have names that are 'like' because the module provides a new namespace!

edit: PS In the above example (not to be too pedantic about it) XLATE becomes a new namespace. The names common to XLATE (part of the my_translations.py module) will NOT conflict with any other names in other namespaces, including the primary namespace (built-ins).
marcus

scruss
Posts: 2895
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

### Re: Python equivalent of map function in Arduino

MarkHaysHarris777 wrote:No, no, no... not at all...

Code: Select all

``````#!/usr/bin/env python

a=[1,2,3]
b=map(lambda x: x+5, a)
print b					# builtin: gives [6, 7, 8]

def map(value, istart, istop, ostart, ostop):
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))

print map(5.0, 4.0, 6.0, 100.0, 200.0) 	# if redefined, prints 150.0

c=map(lambda x: x*5, a)
print c					# so what happens here?``````
Output:

Code: Select all

``````[6, 7, 8]
150.0
Traceback (most recent call last):
File "./valmap-orly.py", line 12, in <module>
c=map(lambda x: x*5, a)
TypeError: map() takes exactly 5 arguments (2 given)
``````
So Python doesn't stop you from redefining a builtin.
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.

MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

### Re: Python equivalent of map function in Arduino

scruss wrote: So Python doesn't stop you from redefining a builtin ...
Of course not ...

... but why would you do that?

Well, these are some reasons; there are probably more...
1) the built-in might not be as robust as the function() you just invented
2) the built-in might be broken
3) the built-in might introduce a side-affect in your environment

edit: PS This is the primary reason for using namespaces... in Python we don't worry about reserved words (names) because our names are neatly tucked inside our namespaces where they won't conflict... unless of course we want them to !
marcus

nautilus27
Posts: 72
Joined: Fri May 22, 2015 9:38 pm

### Re: Python equivalent of map function in Arduino

Thanks everybody, i learnt a lot about Python today.