I am looking for ideas on how to translate one range values to another in Python. I am working on hardware project and am reading data from a sensor that can return a range of values, I am then using that data to drive an actuator that requires a different range of values.

For example lets say that the sensor returns values in the range 1 to 512, and the actuator is driven by values in the range 5 to 10. I would like a function that I can pass a value and the two ranges and get back the value mapped to the second range. If such a function was named `translate`

it could be used like this:

```
sensor_value = 256
actuator_value = translate(sensor_value, 1, 512, 5, 10)
```

In this example I would expect the output `actuator_value`

to be `7.5`

since the `sensor_value`

is in the middle of the possible input range.

One solution would be:

```
def translate(value, leftMin, leftMax, rightMin, rightMax):
# Figure out how 'wide' each range is
leftSpan = leftMax - leftMin
rightSpan = rightMax - rightMin
# Convert the left range into a 0-1 range (float)
valueScaled = float(value - leftMin) / float(leftSpan)
# Convert the 0-1 range into a value in the right range.
return rightMin + (valueScaled * rightSpan)
```

You could possibly use algebra to make it more efficient, at the expense of readability.

You can also use `scipy.interpolate`

package to do such conversions (if you don't mind dependency on SciPy):

```
>>> from scipy.interpolate import interp1d
>>> m = interp1d([1,512],[5,10])
>>> m(256)
array(7.4951076320939336)
```

or to convert it back to normal float from 0-rank scipy array:

```
>>> float(m(256))
7.4951076320939336
```

You can do also multiple conversions in one command easily:

```
>>> m([100,200,300])
array([ 5.96868885, 6.94716243, 7.92563601])
```

As a bonus, you can do non-uniform mappings from one range to another, for intance if you want to map [1,128] to [1,10], [128,256] to [10,90] and [256,512] to [90,100] you can do it like this:

```
>>> m = interp1d([1,128,256,512],[1,10,90,100])
>>> float(m(400))
95.625
```

`interp1d`

creates piecewise linear interpolation objects (which are callable just like functions).

As noted by *~unutbu*, `numpy.interp`

is also an option (with less dependencies):

```
>>> from numpy import interp
>>> interp(256,[1,512],[5,10])
7.4951076320939336
```

Licensed under: CC-BY-SA with attribution

Not affiliated with: Stack Overflow