Python Forum
Help with simplifying a code + np.savetxt()
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help with simplifying a code + np.savetxt()
#1
Hey! I need help simplifying a code. I have a code which plots given data, so you'd only have to create a new data file and the basic Function code itself is the same for each. However, there is a lot of comment-uncomment stuff there that could probably be put in a more sensible manner. Here is the code for the plotting function:

def plot_data(energy, offset, area, width, center, figname):
    fig = plt.figure()
    #plt.errorbar(energy, offset[:,0], yerr=offset[:,1])
    plt.errorbar(energy, area[:,0], yerr=area[:,1])
    #plt.errorbar(energy, width[:,0], yerr=width[:,1])
    #plt.errorbar(energy, center[:,0], yerr=center[:,1])
    plt.ylabel('x')
    plt.xlabel('y')
    plt.legend()
    plt.savefig(figname, Transparent = True)
and here is a part of one data file:
energy=np.arange(1, n_pts+1)
area = np.zeros((n_pts, n_gaussian*4))
offset = np.zeros((n_pts, n_gaussian))
width = np.zeros((n_pts, n_gaussian*4))
center = np.zeros((n_pts, n_gaussian*4))
file = 'Name'
figname = '(the location of the fig in my computer)'
fn.plot_data(energy, offset, area, width, center, figname)
So what I'm wondering is if it is possible to simplify the plot_data function to plot any data that is given as input, so there would be no need to comment-uncomment every time I wish to plot different things? I know that varargin-argument would enable the function to accept any number of input arguments, so could that be of use here?

Another question I have is about the np.savetxt() command. I have two sets of data, transmitted beam intensity and initial beam intensity, I0 and I1, which I have defined like this,

name='I1'
scan_number=np.array([23, 24, 25, 26, 27, 28, 29, 30, 
                      31, 32, 33, 34, 35, 36, 37, 38, 39, 40])
n_pts = 701
n_chnl = 4096
mca_start = 3116

name='I0'
scan_number=np.array([45, 46, 47])
n_pts = 701
n_chnl = 4096
mca_start = 17138]
The point would be to get a file that I could use in data analysis, however even though the code works perfectly, I can't get it to save both I0 and I1 area in one file. I tried defining them separately (I0_area, I0_width etc.) and while that works, it's extremely tedious if there's more than two sets of data, so is there any simpler way to do this? Area, width, offset etc. are now defined once, but the file this creates has two identical area columns, when I wish to have one for I0 values and one for I1, so what I'm asking is if it's possible to have these values saved without defining them separately for each?

The part responsible for saving in my code looks like this (again, has to be simplified somehow)

def savetxt(area, width, offset, center, data, name, energy, file):
    np.savetxt(name + '.area', area)
    np.savetxt(name + '.width', width)
    np.savetxt(name + '.offset', offset)
    np.savetxt(name + '.center', center)
    np.savetxt(name + '.data', data)
    np.savetxt(file,
           np.transpose(([energy, area[:,0], area[:,0]])),
           header='Energy I0 I1 {}'.format(name))
Any help is greatly appreciated! I am very new to coding and all the comment-uncomment stuff makes sense to me as it is very simple, but doesn't look very nice on the code. Sp please note if you have any recommendations on where I could start with - which command etc.!
Reply
#2
Your function used for plotting error-bars doesn't include any specific information, so you can just call plt.errorbar once
within plot_data:

def plot_data(energy, ydata, figname):
    fig = plt.figure()
    plt.errorbar(energy, ydata[:,0], yerr=ydata[:,1])
    plt.ylabel('x')
    plt.xlabel('y')
    plt.legend()
    plt.savefig(figname, Transparent = True)  # Transparend (first letter is uppercased? )
    plt.close('all') 
In the main code you can do the following:

# define an auxiliary variable
what_to_plot = ['area', 'offset']

for what in what_to_plot:
    plot_data(energy, locals().get(what), what + '-fig.png')  # or something similar
You can also rewrite your savetxt function in a similar way.
Reply
#3
Hey, thanks!

The plotting seems to work now, but I seem to have lost the plot as it is now just a straight line at 00.00 and doesn't show any peaks. The code now looks like this:

def plot_data(x, ydata, figname):
    fig = plt.figure()
    plt.errorbar(x, ydata[:,0], yerr=ydata[:,1])
    plt.ylabel('x')
    plt.xlabel('y')
    plt.legend()
    plt.savefig(figname, Transparent = True)
#    plt.close('all')
    
def savetxt(name, x, ydata):
    np.savetxt(name + '.data', what)
    np.savetxt(file,
           np.transpose(([x, area[:,0], area[:,0]])),
           header='Energy I0 I1 {}'.format(name))
With this in the main code, fn being the name I called the functions file with:

what_to_plot = ['area']
what_to_save = ['area', 'offset', 'width', 'center', 'data']

for what in what_to_plot:
   fn.plot_data(x, locals().get(what), what + '-fig.png')
   
for what in what_to_save:
    fn.savetxt(x, locals().get(what), name + what + '.data')
   
There is another problem in the savetxt function, with this error regarding the 'np.savetxt(name + '.data', what)' line:

UFuncTypeError: ufunc 'add' did not contain a loop with signature matching types (dtype('<U11'), dtype('<U11')) -> dtype('<U11')
I have no idea what this error means, only that there must be something wrong with the command I tried to assign.
Reply
#4
You are trying to add a string to an array of strings. The following is an example that reproduces the error:

>>> import numpy as np
>>> x=np.array(['sdf', 'sdf'])
>>> x + 'fsd'
Error:
numpy.core._exceptions.UFuncTypeError: ufunc 'add' did not contain a loop with signature matching types (dtype('<U3'), dtype('<U3')) -> dtype('<U3')
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  issue with numpy.savetxt alyssaantarctica 1 3,916 Jul-13-2018, 03:50 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020