0

As reported below, I have this oscilloscope that saves generated data in .csv, but it saves them as strings. I think, as a beginner with Python, that all the problem is around the write csv function. Infact, I tried to change there "str" with "float" but nothing seems to change, indeed nothing work ....How should I do this? Some suggestion?

import numpy as np
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.animation as animation

PATH_TO_CSV = "dataTank.csv"

class Scope(object):
    def __init__(self, ax, maxt=2, dt=0.02):
        self.ax = ax
        self.dt = dt
        self.maxt = maxt
        self.tdata = [0]
        self.ydata = [0]
        self.line = Line2D(self.tdata, self.ydata)
        self.ax.add_line(self.line)
        self.ax.set_ylim(-.1, 1.1)
        self.ax.set_xlim(0, self.maxt)

    def write_to_csv(self, t, y):
        line_to_be_written = str(t)+","+str(y)+"\n"
        with open(PATH_TO_CSV, "a") as csv:
            csv.write(line_to_be_written)

    def update(self, y):
        lastt = self.tdata[-1]
        if lastt > self.tdata[0] + self.maxt:  # reset the arrays
            self.tdata = [self.tdata[-1]]
            self.ydata = [self.ydata[-1]]
            self.ax.set_xlim(self.tdata[0], self.tdata[0] + self.maxt)
            self.ax.figure.canvas.draw()
        t = self.tdata[-1] + self.dt
        self.tdata.append(t)
        self.ydata.append(y)
        self.line.set_data(self.tdata, self.ydata)
        self.write_to_csv(t, y)
        return self.line,

def emitter(p=0.03):
    'return a random value with probability p, else 0'
    while True:
        v = np.random.rand(1)
        if v > p:
            yield 0.
        else:
            yield np.random.rand(1)

# Fixing random state for reproducibility
np.random.seed(19680801)

fig, ax = plt.subplots()
scope = Scope(ax)

# pass a generator in "emitter" to produce data for the update func
ani = animation.FuncAnimation(fig, scope.update, emitter, interval=10,
                              blit=True)

plt.show()

Thank you so much!

wundolab
  • 177
  • 10

3 Answers3

1

Instead of this,

line_to_be_written = str(t)+","+str(y)+"\n"

try doing it like this,

line_to_be_written = "{time},{value}\n".format(time = t, value = y if type(y)==float else y.item(0))

but, I'm not quite sure I understand what you really want to do. What do you mean by it saves them as strings?

Edit: I tried this, see if this is the result you want. I can't quite point out where y became a list numpy array in your code but that seems to be the problem


You can also try this,

def emitter(p=0.03):
'return a random value with probability p, else 0'
while True:
    v = np.random.rand(1)
    if v > p:
        yield 0.
    else:
        yield float(np.random.rand(1).item(0))

Instead of yielding a np.random.rand(1), you'll instead yield the items in it instead of the whole np array

Dave Mendoza
  • 41
  • 1
  • 4
  • thank you @Dave Mendoza for answer....I mean that in the .csv I see for the variable time (number in format 0.0) and for y as p it appear not 0.0 for example but [0.0]. – wundolab Nov 06 '20 at 09:41
  • I used your code but it seems, unfortunately, that it doesn't work :( – wundolab Nov 06 '20 at 09:44
  • Oh it seems like then that it isn't a str, rather a list. lines_to_be_written = "{time},{value}\n".format(time = t, value = y if type(float) else y[0]) – Dave Mendoza Nov 06 '20 at 09:51
  • @wundolab check my edit on the post, see if that's how you want it. That's a partial fix tho so there can be a better fix – Dave Mendoza Nov 06 '20 at 09:55
  • Sorry, this one should work: line_to_be_written = "{time},{value}\n".format(time = t, value = y if type(y) == float else y.item(0)), turns out it's a numpy array not a list. Also, I made a mistake in the type(float) it should be type(y) == float, I edited my post again to reflect that. See if that works – Dave Mendoza Nov 06 '20 at 10:08
  • dear @Dave Mendoza...it works but gives me the initial problem...so the same problem in a different way...maybe we should try the solution of FloWill – wundolab Nov 06 '20 at 10:22
  • @wundolab I can't comment yet on that thread, but your problem stems from the type of y jumping from float (when it's 0) to a numpy array (when it has values leading to entries like [0.8125] instead of just 0.8125). You can confirm this by having a print(type(y)) on write_to_csv function – Dave Mendoza Nov 06 '20 at 10:29
  • @wundolab I added another solution which instead modifies your emitter function instead of the write_to_csv function, It seems like your emitter function is the one yielding a float when it's 0 and a numpy array otherwise – Dave Mendoza Nov 06 '20 at 10:36
1

Assuming you just want to print the floating point numbers inside your csv function properly, there are answers for that here: https://stackoverflow.com/a/8885688/9898968

Just use a floating point specifier like: {:X.1f} inside the format string. X being the overall character width of the field in the csv. 1 in this case the decimal points printed.

line_to_be_written = "{:5.1f},[{:5.1f}]\n".format(float(t), float(y))

EDIT: Added float conversion to the format arguments. See here for details

FloWil
  • 432
  • 5
  • 15
  • thank you dea @FloWil ...I tried It starts to work, then it stops and gives: line_to_be_written = "{:5.1f},[{:5.1f}]\n".format(t, y) ValueError: Unknown format code 'f' for object of type 'str' – wundolab Nov 06 '20 at 10:06
  • @wundolab That depends on your input data then. The line I posted assumes you already get floats to the function. If it's still strings, try to convert them to float numbers. See Edit. – FloWil Nov 06 '20 at 10:14
  • thank you...is it enough to add the function of the post written by "Cybernetic"? – wundolab Nov 06 '20 at 10:18
  • def string_to_number(str): if("." in str): try: res = float(str) except: res = str elif(str.isdigit()): res = int(str) else: res = str return(res) – wundolab Nov 06 '20 at 10:19
  • Really depends on how your input data looks like. If you only have floats as string in there the cast to float above should be enough. If its float and other data types in there you are properly better of to use some kind of the function you mentioned. – FloWil Nov 06 '20 at 10:26
0

Solved! Thank you very much to @Dave Mendoza and @FloWill from your answers I solved doing a mixing!

    line_to_be_written = "{:5.1f},{:5.1f}\n".format(float(t), float(y))
wundolab
  • 177
  • 10