0

I find some difficulties with fscanf and to do a wavelet transform order 2 on python 3.5. As well, I want to verify if the plot block is right. Here is my Matlab code:

D_P=fopen('distance_profil.txt','r');
i=0;
  while(feof(D_P)==0)% test for end of file
    i=i+1;
    sign=fscanf(D_P,'%f , ');
    classe=fgetl(D_P);
    %Wavelet Transform
    [caH(i,:),cdH(i,:)] = dwt(sign,'db2');         
    %Segmentation    
    loc=[];
    [pks,locs] = findpeaks(abs(cdH(i,:)),'threshold',3);
    loc=[loc,locs];
    mod=abs(cdH(i,:));
    figure
    titre = ['distance profil : ' classe];

    subplot(2,1,1); plot(sign); title(titre); 
    hold on, plot(2*locs,sign(2*locs),'dr')
    subplot(2,1,2); plot(abs(cdH(i,:))); title('Module des Details coef. for db2');
    hold on, plot(locs,mod(locs),'dr')     
end  

And below is my attempt with Python code

import pywt
import numpy as np
from scipy.signal import find_peaks_cwt
from scipy import *
import matplotlib.pyplot as plt

D_P= open ("distance_profil.txt","r")
i=0

while True:
    line = D_P.readline().strip()
    if line == '':

        def ReadFile():
            sign = []
            with open('textfiledata.txt', 'rt') as myFile:
                for line in myFile:
                    sign.append(map(int, line.split(',')))
            return sign

        classe = D_P.readline().rstrip()
        cA= np.array(sign)
        cD= np.array(sign)

        i+=1

        array[cA[i,], cD[i,]] = pywt.dwt([sign, 'db2'])

        loc = []
        [pks,locs] = find_peaks_cwt(abs(cdH([i,]),'threshold',3)

        loc = [loc,locs]
        mod=abs(cdH[i,])  

        plt.figure()
        plt.subplot(2,2,1)
        plt.plot(sign,2*locs,sign(2*locs),'ro')
        plt.title('distance profil : ' , classe)

        plt.subplot(2,2,2)
        plt.plot(abs(cdH(i,)),locs,mod(locs),'ro')
        plt.title("Module des Details coef. for db2")

        plt.show()

    break
RubenLaguna
  • 21,435
  • 13
  • 113
  • 151

1 Answers1

4

The two problems are that your Python code is not doing the same thing as your MATLAB code in a lot of places, and your Python code is invalid in multiple places.

First, in the MATLAB code, this line continues to loop until you reach the end of the file: while(feof(D_P)==0)%. You apparently are trying to do the same thing with this line in python: if line == '':. However, that runs the code only if the line is blank.

You can use this approach in python, but you shouldn't. You can just loop over the lines as though they were an array, using for line in D_P:. This will automatically loop over the lines of D_P, putting each line in variable line. Also, you should use with open ("distance_profil.txt","r") as D_P: to safely open and close the file, as is done in the ReadFile function. And you can use enumerate to keep track of the index with for i, line in enumerate(D_P):. You also try to read each line twice, which means you really end up reading every other line.

The next problem is with this line cA= np.array(sign). You do not define the sign variable anywhere. It is defined in the ReadFile() function, which you never use and should delete. So instead of using the sign variable, it is instead using the scipy.sign function, which you would have overriden if you had defined the sign variable. That is why from ___ import * is a bad idea. Use import scipy as sp or something like that. However, you don't need that since you only use one scipy function, which you import separately.

Unlike in MATLAB, functions are first-class objects in Python. You can use them like any other variable. So you are creating an array containing one function rather than the numeric data you apparently intend. This fails, however, for the dwt function, which needs numeric input. What you need to do is convert the line of text into an array of numbers. The approach used in ReadLine is okay, except it is reading the wrong file and read the entire file instead of one line, did you copy that from somewhere? However, it isn't a very good approach. It is better to use np.fromstring(line.strip(), sep=' '). This will interpret a string as a sequence of numbers separated by spaces (replace with whatever you need) and convert it into a numpy array. This is faster and easier.

Next, with the dwt function, you assign to array[cA[i,], cD[i,]]. This isn't doing what you want and won't work because there is no array variable. If array were a 2D numpy array, this would assign the results of dwt to the indexes at the coordinate corresponding to the value at index i of cA and cD. You just want to assign to cA and cD. That means you can also remove the earlier definitions of cA and cD.

Then, with the dwt call, you wrap the inputs in []. In Python this passes a list as a single argument rather than the two arguments you want. In MATLAB it wouldn't work either, since it would try to concatenate a numeric array with a character array (which will fail) and will also pass that as a single input to the function. So do pywt.dwt(sign, 'db2').

So that line would be: cA, cD = pywt.dwt(sign, 'db2').

Also, you use cdH several places, but never define it. Is it supposed to be cD? Also with cdH([i,]), MATLAB doesn't differentiate between function calls and array access, but python does. You need to use square brackets [] and only square brackets for indexing. cdH([i,]) will be interpreted as "call the function cdH with the list input [i,], which won't work because cdH isn't a function (or wouldn't be if it were defined). The trailing comma is also redundant. So you just do cdh[i].

Next, you define loc as an empty list, then define locs, then do loc = [loc, locs]. In MATLAB, this appends locs to loc (which is redundant, but valid). In python, however, this creates a list that looks like [[], locs], which is completely different. You should just reduce those three lines to [pks,loc] = find_peaks_cwt(abs(cdH([i,]),'threshold',3).

Also, below, you write sign(2*locs). As I said, you need to use brackets for indexing, so this needs to be sign[2*locs].

Next, python doesn't have a mod function. Use % to do modulus in Python. I am not sure what the mod with a single argument does in your version of MATLAB, in mine it raises and error. I assume from context, however, that you are trying to get the fractional part, which would be locs%1.

Finally, you do plt.plot(abs(cdH(i,)),locs,mod(locs),'ro'). Neither MATLAB nor Python would know how to plot with three arrays like this. You either need to split plt.plot(abs(cdH(i,))) into its own plot command like the MATLAB code does, or put np.arange(len(cdH(i,))) as the first argument to plot. Same with the other plot.

Overall, it seems like you aren't very familiar with either MATLAB or Python (or both). It would be worthwhile to brush up on the basics of both before trying to write code like those again.

TheBlackCat
  • 9,791
  • 3
  • 24
  • 31