1

I'm using matplotlib to iterate a bunch of measurements over telnet...I set up the measurement with telnetlib and then read in the data, and set it up to be plotted. The problem is, I want it in engineering notation (exponents to multiples of three, so, kilo, mega, giga, etc.). However, I cannot make this work...Please see the code below...You'll notice I have commented out my latest attempt to force engineering notation with a call to a function that I defined manually.

Any thoughts on how to do this?

import os
import telnetlib
import time
import csv
import sigan 
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

from decimal import Decimal

def eng(num):
   return Decimal(num).normalize().to_eng_string() 

print("What board revision is this?")  # This name will be appended to the output files
board=input()
print("How long should I wait for the measurements to settle each time in seconds?")  # This name will be appended to the output files
rest=int(input())

## Setup the Telnet link ##

HOST = "192.168.0.118"
tn = telnetlib.Telnet(HOST, "5024")

## Initialize the SA to a known State ##
sigan.initialize_sa(tn)


frequencies = [["30","100"],["100","500"],["500","1000"],["1000","2398"],["2485","3000"],["3000","3500"],["3500","4000"],["4000","4500"],["4500","5000"],["5000","5500"],["5500","6000"]]
frequencies = [[str.encode(c) for c in s] for s in frequencies]

tn.write(b'disp:wind:trac:y:rlev -25\r\n')
tn.read_until(b'SCPI>')
tn.write(b'pow:aran on\r\n')
tn.read_until(b'SCPI>')
tn.write(b'disp:wind:trac:y:pdiv 3\r\n')
tn.read_until(b'SCPI>')
tn.write(b'trac:type maxh\r\n')
tn.read_until(b'SCPI>')
tn.write(b'band:res 100khz\r\n')
tn.read_until(b'SCPI>')


for i in range(len(frequencies)):
    if float(frequencies[1][0])>=1000:
        tn.write(b'band:res 1mhz\r\n')
        tn.read_until(b'SCPI>')

    print('Setting up the Analyzer for ' + str(frequencies [i][0]) + ' to ' + str(frequencies[i][1]) + ' Mhz')
    tn.write(b'sens:freq:stop '+frequencies[i][1]+b'mhz\r\n')
    tn.read_until(b'SCPI>')
    tn.write(b'sens:freq:star '+frequencies[i][0]+b'mhz\r\n')
    tn.read_until(b'SCPI>')
    print('Working on '+str(frequencies[i][0])[2:-1]+'MHz to ' +str(frequencies[i][1])[2:-1]+'MHz')
    print('Letting Maximum values settle out for ' + str(rest) + ' seconds') 
    time.sleep(rest)
    tn.write(b'trac1:upd off\r\n')
    tn.read_until(b'SCPI>')
    tn.write(b'read:san?\r\n')
    data=tn.read_until(b'SCPI>')

    tn.write(b'trac1:upd on\r\n')
    tn.read_until(b'SCPI>')
    data=data[:-7]
    data=np.fromstring(data.decode(),float,sep=',')

    x = data[::2]
    x_line=[30E6,6000E6]
    y_line=[-30,-30]
    y = data[1::2]
#    x = [eng(s) for s in x]



    plt.title(board+' at '+str(frequencies[i][0])[2:-1]+'MHz to '+str(frequencies[i][1])[2:-1]+'MHz')
    plt.xlabel('Frequency')
    plt.ylabel('Conducted Power (dBm)')
    plt.ylim(-60,-25)
    plt.xlim(float(x[1]),float(x[-1]))
    if (y>-30).sum():
        failure=mpatches.Patch(color='red', label='Failure')
        plt.legend(handles=[failure])
    else:
        success=mpatches.Patch(color='green', label='Success')
        plt.legend(handles=[success])
    plt.grid(True)
    plt.plot(x,y)
    plt.plot(x_line,y_line, color='r', linestyle='dashed', marker='x', markerfacecolor='black', markersize=12, lw=3, label='Threshold') 
    plt.savefig(board+"_"+str(frequencies[i][0])[2:-1]+"_"+str(frequencies[i][1])[2:-1])
    plt.cla()







print("Test Finished and Images Written to '" + os.getcwd() + "'.  SUCCESS!")
tn.close()
testname123
  • 1,061
  • 3
  • 20
  • 43

2 Answers2

0

One way is to get the tick-values and then format them and set the new formatted ones as labels. Look here for an example of the formatting. Sample code might be

xticks = ax.get_xticks()
formatted_ticks = formatter_from_link_function(xticks)
ax.set_xticklabels(formatted_ticks)

Another idea which might be a bit of overkill in your case is to use a user-defined formatter-function to the ticks. Here is an example how to do that. With your own function formatter you can even return the string "kilo", "Mega", "atto" or whatever you like if you prefer that instead of the numerical "10e-3".

Community
  • 1
  • 1
pathoren
  • 1,634
  • 2
  • 14
  • 22
0

Matplotlib has the solution, at least if you are OK with the SI prefixes,

from matplotlib.ticker import EngFormatter
fmt = EngFormatter(unit='m', places=2)
print(fmt(1234), fmt(12345), fmt(123456), fmt(1234567), sep=', ')
1.23 km, 12.35 km, 123.46 km, 1.23 Mm

In your script, you can use EngFormatter like in the following

...
fig, ax = plt.subplots()
ax.xaxis.set_major_formatter(EngFormatter(unit='m', places=2))
ax.yaxis.set_major_formatter(EngFormatter(unit='W', places=2))
...

Addendum

Even if you dislike very much the use of SI prefixes (maybe you were raised in, say, Liberia) you can the same use the EngFormatter, just modify the strings it uses for the prefixes (see the source). These strings are contained in a dictionary, that's an attribute of EngFormatter

fmt = EngFormatter()
fmt.ENG_PREFIXES = {i:"10**%d"%i if i else '' for i in range(-24, 25, 3)}
gboffi
  • 22,939
  • 8
  • 54
  • 85