changeset 0:0d2d20ef6e72 draft

Uploaded
author jcb-mpl
date Tue, 27 Apr 2021 13:52:21 +0000
parents
children 96cffbbe245e
files 2018_07_centroids.xml src/mz_1bis_signal_threshold.sci src/mz_2_barycenter_adjust2.sci src/mz_2_savgol2.sci src/mz_3_remove_zeros.sci src/mz_eic5_step1.sci src/mz_hdf5tosci.sci src/savgol_xl.sci test-data/VI2016_AC_4Areduit_1.dat test-data/VI2016_AC_4Areduit_1.h5 test-data/VI2016_AC_4Areduit_1centroide.mat
diffstat 11 files changed, 836 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2018_07_centroids.xml	Tue Apr 27 13:52:21 2021 +0000
@@ -0,0 +1,207 @@
+<tool id="2021_05_centroids" name="MS .h5 or .dat -> MS-centroid" version="0.0.1">
+
+<description>    </description>
+
+<requirements>
+    <requirement type="package" version="6.0.2">scilab</requirement>
+</requirements>
+
+
+<stdio>
+    <exit_code range="1:" level="fatal" />
+</stdio>
+
+
+<command> 
+ <![CDATA[ 
+ if [ -d $__root_dir__/packages/scilab-6.1.0 ]; then $__root_dir__/packages/scilab-6.1.0/bin/scilab-cli -nb -quit -f $* < ${script_file}; else scilab-cli -nb -quit -f $* < ${script_file}; fi 
+ ]]>
+</command>
+
+  <configfiles>
+    <configfile name="script_file">
+    <![CDATA[ exec("$__tool_directory__/src/mz_1bis_signal_threshold.sci",-1); ...
+        exec("$__tool_directory__/src/mz_2_barycenter_adjust2.sci",-1); ...
+        exec("$__tool_directory__/src/mz_2_savgol2.sci",-1); ...
+        exec("$__tool_directory__/src/mz_3_remove_zeros.sci",-1); ...
+        exec("$__tool_directory__/src/mz_eic5_step1.sci",-1); ...
+        exec("$__tool_directory__/src/mz_hdf5tosci.sci",-1); ...
+        if ~isdef('pls') then ...
+            atomsSystemUpdate(); ...
+            atomsInstall('FACT'); ...
+            atomsLoad('FACT'); ...
+        end; ...
+        lasterror(); ...
+        type_sm=${type_sm}; ...
+        format_io=${format_io}; ...
+        if type_sm==1 then           ...    // mode profil Orbitrap
+            if format_io==0 then     ...    // format Scilab
+                load("${filein}");   ...    // la variable doit s'appeler res
+            elseif format_io==1 then ...    // format HDF5
+                res=mz_hdf5tosci("${filein}"); ...
+            end; ...
+            resbary=mz_eic5_step1(res,${signalthresh}); ...
+        elseif type_sm==0 then      ...    // mode centroide
+            if format_io==0 then    ...    // format Scilab = on ne fait rien 
+                load("${filein}");  ...    // la variable doit deja s'appeler resbary
+            elseif format_io==1 then ...   // format HDF5
+                res=mz_hdf5tosci("${filein}"); ...
+                resbary=mz_3_remove_zeros(res); ...
+            end; ...
+        end; ...
+        save("${resbary}",'resbary'); ...
+        if ~isempty(lasterror(%f)) then ...
+        write(0,lasterror()); ...
+        end; ]]>
+</configfile>
+  </configfiles>
+
+
+  <inputs>
+    <param name="format_io" type="select" size="5" format="integer" label="MS format" >
+        <option value="0" selected="true" > Scilab format .dat </option>
+        <option value="1"   > HDF5 format .h5 </option>
+    </param>
+    <param name="filein"       format="mat,h5,dat"                type="data"      label="MS data"    />
+    <param name="signalthresh" size="5"         value="0"  type="integer"   label="Baseline threshold"  help="if not applied during the spectrum acquisition"  />
+    <param name="type_sm" type="select" size="5" format="integer" label="Mode during spectrum acquisition" help="if centroid: 0 are removed; if profile: centroids are calculated" >
+        <option value="0" selected="true" > Centroid </option>
+        <option value="1"   > Profile mode with Orbitrap </option>
+    </param>
+  </inputs>
+
+
+  <outputs>
+    <data name="resbary"    format="mat"   label="MS-centroid"  >
+    </data>
+  </outputs>
+  
+  
+   <tests>
+   
+    <test>
+       <param name="format_io"    value="0"/>
+       <param name="filein"       value="VI2016_AC_4Areduit_1.dat"/>
+       <param name="signalthresh" value="0"/>
+       <param name="type_sm" value="1"/>
+       <output name="resbary"   file="VI2016_AC_4Areduit_1centroide.mat" compare="sim_size" delta="2000" />
+    </test>
+
+    <test>
+       <param name="format_io"    value="1"/>
+       <param name="filein"       value="VI2016_AC_4Areduit_1.h5"/>
+       <param name="signalthresh" value="0"/>
+       <param name="type_sm" value="1"/>
+       <output name="resbary"   file="VI2016_AC_4Areduit_1centroide.mat" compare="sim_size" delta="2000" />
+    </test>
+
+  </tests>
+  
+  
+  <help>
+
+
+**Author**  Jean-Claude Boulet (INRAE).
+
+
+---------------------------------------------------
+
+====================
+CENTROID CALCULATION
+====================
+
+-----------
+Description
+-----------
+
+
+Centroids are calculated according to the reference cited below. 
+
+
+------
+Inputs
+------
+
+**MS format**
+
+Two formats are possible: HDF5 obtained from Scilab (.dat) or HDF5 obtained from MSconvert then HDFView (.h5)
+
+The Scilab format contains a structure with two fields: 
+
+- time: the retention times, a vector;
+
+- mzdata: a list of same length as time; each element of the list is a matrix of two columns representing a MS1 mass spectrum: m/zvalues and associated signals.
+
+The HDF5 (.h5) file contains at least the following fields: 
+
+- ChomatogramTime: a vector containing the retention times of each mass spectrum. 
+
+- ChromatogramIndex: the indexes of the signals identified in ChomatogramTime; the last value of ChromatogramIndex is the size of ChomatogramTime.
+
+- ChromatogramIntensity: the sum of intensities of the mass spectra associated to the RTs of ChomatogramTime; ChomatogramTime and ChromatogramIntensity are vectors of same length.
+
+- SpectrumIndex: a vecteur of integers corresponding to the numbers of signals of each MS in SpectrumMZ et SpectrumIntensity. For example, if the two first values of SpectrumIndex are 1421 and 2887, then the first MS is between 0 à 1421, the second between 1422 and 2887. The last value of spectrumIndex is the number of values in SpectrumMZ and in SpectrumIntensity.
+
+- SpectrumMz: the m/z values. For each mass spectrum, the first value is the real m/z value, but the following are obtained by the sum of the previous values. For example, if the three first values are: 220.0501, 0.1171 and 0.9856, then the real m/z values to be calculated will be: 220.0501, 220.1672=220.0501+0.1171, 220.2528=220.0501+0.1171+0.9856.
+
+- SpectrumIntensity: a vector containing all the intensities recorded.
+
+Even if the MS spectrum has been obtained with the centroid option of MSconvert, this function should be applied to remove all the zeros kept by the MSconcert peak picking option. 
+
+
+**MS data**
+
+The mass spectrum
+
+
+----------
+Parameters
+----------
+
+
+**Baseline threshold**
+
+Signals under the threshold are dropped. Default value = 0. 
+
+Most of the peaks should be separated by regions with signal=0. 
+
+
+**Mode during spectrum acquisition**
+
+Profile or centroid.
+
+
+
+-------
+Outputs
+-------
+
+**MS-centroid**
+
+For each RT, the signals associated to the same m/z value have been replaced by their centroid. 
+
+The output is a structure with two fields: 
+
+- time: retention times;
+
+- mzdata: m/z values and centroid signals.
+
+
+</help>
+
+
+<citations>
+
+<citation type="bibtex">@article{sgcentroid,
+   title={High-resolution mass spectrometry (HRMS): focus on the m/z values estimated by the Savitzky-Golay first derivative},
+   author={Boulet, J.C. and Meudec, E. and Vallverdu-Queralt, A. and Cheynier, V.},
+   journal={Rapid Communications in Mass Spectrometry},
+   year={2020},
+   doi={10.1002/rcm.9036}
+   }
+</citation> 
+
+</citations>
+
+
+</tool>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mz_1bis_signal_threshold.sci	Tue Apr 27 13:52:21 2021 +0000
@@ -0,0 +1,22 @@
+function res2=mz_1bis_signal_threshold(res,sigthresh);
+    
+    res2=res;
+    
+    n=max(size(res2.time));
+    
+    for i=1:n;
+        resi=res2.mzdata(i);
+        
+        resi_col2=resi(:,2);
+        
+        // application du seuil
+        resi_col2(resi_col2<sigthresh)=0;
+        
+        resi(:,2)=resi_col2;
+        
+        res2.mzdata(i)=resi;
+    end
+    
+    
+    
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mz_2_barycenter_adjust2.sci	Tue Apr 27 13:52:21 2021 +0000
@@ -0,0 +1,28 @@
+function xout=mz_2_barycenter_adjust2(xin)
+    
+    // remplace les donnees brutes par: 
+    // (1) mz barycentrique
+    // (2) somme des signaux
+
+    // xin: une structure avec 2 champs: 
+    // xin.time
+    // xin.mzdata
+    
+    // xout: 2 champs, comme xin
+    
+    // re-ecrit totalement et simplifie le 9dec20
+    
+    xout.time=xin.time;
+    xout.mzdata=list();
+    n=max(size(xin.time));    
+
+    for i=1:n;
+       xtemp_in=xin.mzdata(i);
+       [nul,xtemp_out]=mz_2_savgol2(xtemp_in);
+       xout.mzdata(i)=xtemp_out;
+    end 
+  
+    
+    
+    
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mz_2_savgol2.sci	Tue Apr 27 13:52:21 2021 +0000
@@ -0,0 +1,221 @@
+function  [xout2,xout3,no_pic,signe_d1]=mz_2_savgol2(xin)
+    
+    // xin: une matrice de 2 colonnes 
+    // 1° colonne = valeurs de m/z successives 
+    // 2° colonne = intensités de signal 
+ 
+    // xout: un vecteur-ligne ou matrice de 3 colonnes
+    // dans l'ordre: m/z_min m/z_savgol m/z_max  
+    
+    // xout2: une matrice de 2 colonnes 
+    // 1° colonne = valeurs de m/z remplacées par leur barycentre 
+    // 2° colonne = intensités de signal 
+    
+    // xout3: une matrice de 2 colonnes 
+    // 1° colonne: m/z (uniques)
+    // 2° colonne: somme des intensités de signal 
+ 
+ 
+//    // marche bien avec l'exemple ci-dessous, 9 ou 18 premières lignes  
+//    xin_1=[
+//    775.08677  804.23633;
+//    775.09492   19743.041;
+//    775.10307   62518.859;
+//    775.11123   100056.77;
+//    775.11938   108296.29;
+//    775.12753   83583.969;
+//    775.13568   45296.258;
+//    775.14384   15782.141;
+//    775.15199   2796.1245;
+//    775.16014   3257.4946;
+//    775.1683    17404.266;
+//    775.17645   41285.391;
+//    775.1846    61480.969;
+//    775.19276   65116.719;
+//    775.20091   50944.094;
+//    775.20906   29804.268;
+//    775.21722   12828.898;
+//    775.22537   2491.0898];
+//    
+// ou sur: 
+//   355.6344    8. 
+//   355.64264   8. 
+//   355.65088   10.
+//   355.65909   7. 
+//   355.66733   4. 
+//   355.67557   11.
+//   355.68381   40.
+
+// ou cet exemple 
+//
+//   x=[102.12401   0.    ;   
+//   102.12428   0.       ;
+//   102.12457   0.       ;
+//   102.12485   0. ;
+//   102.12513   0.  ;     
+//   102.1254    0.   ;    
+//   102.12568   18844.752;
+//   102.12596   70650.805;
+//   102.12623   130295.48;
+//   102.12651   187543.03;
+//   102.12679   521590.84;
+//   102.12707   1696004. ;
+//   102.12734   3549963.2;
+//   102.12762   5541599. ;
+//   102.1279    5764036. ;
+//   102.12817   3820761.2;
+//   102.12845   1933240. ;
+//   102.12873   544016.81;
+//   102.129     120472.32;
+//   102.12928   50397.285;
+//   102.12956   20005.551;
+//   102.12983   0.       ;
+//   102.1301    0. ;
+//   102.13038   0.  ;     
+//   102.13065   0.   ;    
+//   102.13093   0. ];
+
+
+// 
+    // choix du traitement selon la taille de n
+    
+    n=size(xin,1);
+    no_pic=zeros(n,1);
+    
+    if n<3 then 
+        all_pics=[];    // on ne traite pas 
+       
+        
+    elseif n==3 then
+        all_pics=zeros(1,3);
+        all_pics(1)=xin(1,1);
+        all_pics(3)=xin(3,1);
+        all_pics(2)=xin(2,1);
+   
+        
+    elseif n==4 then 
+        all_pics=zeros(1,3);
+        all_pics(1)=xin(1,1);  // m/z min
+        all_pics(3)=xin(4,1);  // m/z max 
+        x1=xin(2,1);
+        x2=xin(3,1);
+        y1=xin(2,2);  
+        y2=xin(3,2);   
+        x0=(x2*y1-x1*y2)/(y1-y2);
+        all_pics(2)=x0;
+   
+        
+    elseif n>4 then 
+        // calcul des dérivées 1°
+        d1=savgol_xl(xin(:,2)',5,1); 
+        // Obtention des signes: 
+        signe_d1=sign(d1.d);
+        
+        // recherche des valeurs de signal nulles //8dec20
+        ind_null=find(xin(:,2)==0);
+        signe_d1(ind_null)=0;
+        
+  //  pause    
+        // correction des valeurs nulles 
+   
+   // 8dec20     
+//        // correction des bords de Savgol:
+//        signe_d1(1)=1;
+//        signe_d1(2)=1;
+//        signe_d1($-1)=-1;
+//        signe_d1($)=-1;
+      
+        // suppression le 31 mai 18 --------------------------  -> pas de lissage si pics intercallés, ex: ex: -1 -1 1 -1 -1
+
+        // identification des pics par des n°: 1, 2, 3, etc.  27juin17
+        no_pic=zeros(n,1);
+        no_pic(1)=1;
+        for i=2:n;
+           if signe_d1(i-1)<0 & signe_d1(i)>=0 then
+               no_pic(i)=no_pic(i-1)+1;
+           else
+               no_pic(i)=no_pic(i-1);
+           end
+        end
+  
+        
+        // identification des pics
+        all_pics=[];
+        // pour chaque pic
+        i=1;
+        pic=zeros(1,3);
+        
+        while i<=n;                
+            if pic(1)==0 then 
+                pic(1)=xin(i,1);
+            end
+            if i<n & signe_d1(i+1)< signe_d1(i)  then   // un sommet 
+                x1=xin(i,1);
+                x2=xin(i+1,1);
+                y1=d1.d(i);
+                y2=d1.d(i+1);
+                x0=(x2*y1-x1*y2)/(y1-y2);             // calcul précis du m/z 
+                pic(2)=x0;
+            elseif i<n & signe_d1(i+1)> signe_d1(i) & pic(2)==0 then
+                pic=zeros(1,3);                         // 3oct18 fin de la boucle sans rien faire 
+
+            elseif i<n & signe_d1(i+1)> signe_d1(i) & pic(2)~=0 then   // une vallée 
+                pic(3)=xin(i,1);
+                if all_pics==[] then 
+                    all_pics=pic;
+                else
+                    all_pics=[all_pics;pic];
+                end 
+                pic=zeros(1,3);   
+            elseif i==n & pic(1)~=0 & pic(2)~=0 then 
+                pic(3)=xin(i,1);
+                if all_pics==[] then 
+                    all_pics=pic;
+                else
+                    all_pics=[all_pics;pic];
+                end 
+            end
+            i=i+1;
+        end
+        
+        if size(all_pics,1)== max(no_pic) then // 3oct18
+            break
+        end
+    end
+
+    // sortie du résultat
+    xout=all_pics;
+    
+    xout2=xin;   // 27juin17
+    n_out=size(xout,1);
+    if no_pic($)~=0 & no_pic($) ~=[] then
+        n_pics=no_pic($); 
+        //if n_out ~=n_pics then                //3oct18
+            //disp('ligne 154')
+            //pause
+            //error('n_out different de n_pics')
+        //end 
+        for i=1:n_out;
+            liste_pics=find(no_pic==i);
+            xout2(liste_pics,1)=xout(i,2);
+        end
+    end
+    
+    // somme des signaux 9mai18
+    xout2_unique=unique(xout2(:,1));
+    n_unique=max(size(xout2_unique));
+    xout3=zeros(n_unique,2);
+    xout3(:,1)=xout2_unique;
+    for i=1:n_unique;
+        tri=find(xout2(:,1)==xout3(i,1));
+        sum_signals=sum(xout2(tri,:),'r');
+        xout3(i,2)=sum_signals(2);
+    end
+    
+    
+    // tri de xout3 (enlever les valeurs de signal nulles)  7dec20
+    tri2=find(xout3(:,2))~=0;
+    xout3=xout3(tri2,:);  
+   
+    
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mz_3_remove_zeros.sci	Tue Apr 27 13:52:21 2021 +0000
@@ -0,0 +1,18 @@
+function x_out=mz_3_remove_zeros(x_in)
+    
+    // x_in: un fichier au format barycentrique avec 2 champs: .time et .mzdata 
+    // si le calcul centroide a été fait par MSconvert, le fichier contient des m/z avec signal=0: on va les enlever 
+    
+    // initialisation
+    x_out.time=x_in.time;
+    x_out.mzdata=list();
+    
+    n=max(size(x_in.time));
+
+    for i=1:n;
+        mzdata_i=x_in.mzdata(i);
+        index=find(mzdata_i(:,2)>0);
+        x_out.mzdata(i)=mzdata_i(index,:);
+    end
+    
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mz_eic5_step1.sci	Tue Apr 27 13:52:21 2021 +0000
@@ -0,0 +1,45 @@
+function resbary=mz_eic5_step1(res,sigthresh)
+     
+    // cette fonction mobilise les fonctions suivantes:
+    //  exec('mz_1bis_signal_threshold.sci',-1);
+    //  exec('mz_2_barycenter_adjust2.sci',-1);   
+    //  exec(‘mz_2_savgol2.sci’,-1);   
+
+    // Arguments:
+    // res: une variable avec 2 champs: time et mzdata
+    // sigthresh: un seuil pour un seul signal sur un seul TR ; ex: sigthresh=10000
+    
+    // resbary: un fichier barycentrique 
+
+    
+    res=mz_1bis_signal_threshold(res,sigthresh);
+    
+    resbary=mz_2_barycenter_adjust2(res);   
+
+
+endfunction
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mz_hdf5tosci.sci	Tue Apr 27 13:52:21 2021 +0000
@@ -0,0 +1,103 @@
+function x_mz=mz_hdf5tosci(file_in,max_scans)
+    
+    // entrees: -------------------------
+    // file_in: un fichier au format HDF5 
+    // max_scans: valeur introduite pour accelerer la fonction de test
+    
+    // sorties: ---------------------------
+    // x_mz: une variable avec deux champs:
+    // x_mz.time
+    // x_mz.mzdata une liste dont chaque élément est un vecteur de 2 colonnes: m/z et intensités de signal
+    
+    // JCB 2 aout18
+    
+    h5close()
+    
+    // lecture du fichier HDF5 ----------------------------------
+    a=h5open(file_in,'r','stdio');  // que lecture   6jan20:stdio 
+    //pause
+    spectrum_chromatogram_index=h5read(a.root.ChromatogramIndex);
+    spectrum_chromatogram_index=spectrum_chromatogram_index(1);    // une valeur 
+    spectrum_time=h5read(a.root.ChomatogramTime);
+    spectrum_intensity=h5read(a.root.SpectrumIntensity);
+    spectrum_mz=h5read(a.root.SpectrumMZ);
+    spectrum_index=h5read(a.root.SpectrumIndex);                    
+    //spectrum_index=spectrum_index(1:spectrum_chromatogram_index); 
+    h5close(a)
+    
+    // reconstruction du spectre -----------------
+    if argn(2)<2 then
+        nbr_scans=max(size(spectrum_index));
+    else
+        nbr_scans=max_scans;
+    end
+
+ 
+    // 1- extraction du temps
+    //25juin20
+    time=spectrum_time;   
+    if size(time,1)==1 then
+        time=time';
+    end
+    //pas=(spectrum_time($)-spectrum_time(1))/(nbr_scans-1);
+    //time=[spectrum_time(1):pas:spectrum_time($)+pas]; // rajout de 1 par securite pour être sur d'arriver a nbr_scans 
+    //time=time(1:nbr_scans);    // nbr exact de RT 
+
+    mzdata=list();
+    
+    //disp(nbr_scans,'nbr_scans=')
+    
+    for i=1:nbr_scans;
+        if i==1 then 
+            plage_i=[1,double(spectrum_index(i))];
+        else 
+            plage_i=[double(spectrum_index(i-1))+1,double(spectrum_index(i))];
+        end
+        //disp(plage_i,'plage_i=')
+        // 2- extraction et reconstruction des m/z
+        // dans le fichier HDF5, ne sont enregistrées que les différences de m/z entre 2 mesures
+        mz_i=spectrum_mz(plage_i(1):plage_i(2));
+        
+        n=size(mz_i,2);
+        mz_i2=zeros(1,n);
+        
+        mz_i2(1)=mz_i(1);
+        for j=2:n;
+            mz_i2(j)=mz_i2(j-1)+mz_i(j);
+        end
+        
+        // 3- extraction des signaux
+        sig_i=spectrum_intensity(plage_i(1):plage_i(2));
+
+        // regroupement des m/z et signaux
+        sp_i=[mz_i2;sig_i];
+        
+        mzdata(i)=sp_i';
+       
+        
+    end
+    
+    // verif. que time est un vecteur colonne
+    if size(time,2)>1 then
+        time=time';
+    end
+    
+
+    // amelioration de la coherence des donnees 
+    index=time(2:$)-time(1:$-1);
+    index2=find(index<0);
+    if index2 ~=[] then
+        index3=min(index2); 
+    else;
+        index3=max(size(time));
+    end
+    
+    x_mz.time=time(1:index3);
+    mzdata2=list();
+    for i=1:min(index3,size(mzdata));             
+        mzdata2(i)=mzdata(i);
+    end
+    x_mz.mzdata=mzdata2;
+    
+    
+endfunction
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/savgol_xl.sci	Tue Apr 27 13:52:21 2021 +0000
@@ -0,0 +1,192 @@
+function[res_savgol]=savgol_xl(saisir,window2,d012,degre_polynom)
+    //
+    // Algorithme basé sur Savitzsky-Golay (SG), NON modifiée cad projection 
+    // sur trois axes non orthogonaux entre eux
+    //
+    // ------------------------------------------------------------------------
+    // Entrées: 
+    //    saisir:       matrice au format Saisir ou bien matrice classique 2D
+    //    plage:        nombre entier positif impair >=3
+    //    d012:         dérivée (0, 1 ou 2)
+    //    degre_polynom: degré du polynome; par défaut: 2 
+    // Sorties:
+    //    res_savgol    spectres après application de d012
+    //    filter_d012:  un filtre F tel que: X après dérivée d012= X.F
+    // ------------------------------------------------------------------------
+    //
+    // Avertissement: 
+    // SG ne gère pas les demi-plages à droite et à gauche. Celles-ci 
+    // sont approximées au mieux par régression aux moindres carrés, mais le 
+    // résultat est toujours nettement moins bien que lorsque SG est applicable.
+    // En conséquence les extrémités droite et gauche sont perturbées,
+    // et la perturbation s'amplifie avec le degré de dérivation
+    // 
+    // Avec les filtres, c'est encore pire pour d1 et d2 
+    // ------------------------------------------------------------------------
+
+
+    //Vérification/transformation en matrice Saisir:  
+    saisir=div(saisir);
+                 
+    //vérification de l'absence de valeurs manquantes
+    test=sum(sum(isnan(saisir.d)));
+    if(test>0) then
+        xdisp('There are ',test,' Nan values in the data table');
+        xdisp('It is necessary to resolve the problem before using savgol');
+        error(' ');
+    end
+
+
+    // choix du degré du polynome
+    if argn(2)==4 then
+        degre=degre_polynom;
+    else
+        degre=2;       // degré 2 
+    end
+
+    if degre<2 | degre>5 then
+        error('the degree of the polynom should be between 2 and 5')
+    end
+
+
+    //Initialisation:
+    [n,p]=size(saisir.d);
+    filter_d0.d=zeros(p,p);  //9mars18
+    filter_d1.d=zeros(p,p);
+    filter_d2.d=zeros(p,p);
+    
+    rayon=floor((window2-1)/2);
+    plage=2*rayon+1;
+  
+    // verification de la fenêtre          
+    if rayon<1 | plage ~= window2 then 
+        error('the window should be an odd integer, equal to 5 or more ');
+    end
+
+    d0_savgol=saisir.d;
+    d1_savgol=ones(n,p);
+    d2_savgol=ones(n,p);
+    m=zeros(6,plage);
+
+
+    // ---------------------------------------------------------
+    // calculs de Savitzsky-Golay sur le spectre, cotés exceptés 
+    // ---------------------------------------------------------
+
+    //Calcul de m  
+    vecteur=[-rayon:1:rayon];
+    m(1,:)=vecteur.^0;  
+    m(2,:)=vecteur.^1;  
+    m(3,:)=vecteur.^2;  
+    m(4,:)=vecteur.^3;  
+    m(5,:)=vecteur.^4;  
+    m(6,:)=vecteur.^5;  
+    
+    // ajustement de m à la dimension du polynome
+    m=m(1:degre+1,:);   
+
+    c=inv(m*m')*m; 
+
+    for a=rayon+1:p-rayon;  // -1;  12mars18
+        d0_savgol(:,a)=saisir.d(:,a-rayon:a+rayon)*c(1,:)';
+        d1_savgol(:,a)=saisir.d(:,a-rayon:a+rayon)*c(2,:)';
+        d2_savgol(:,a)=2*saisir.d(:,a-rayon:a+rayon)*c(3,:)';
+        //la multiplication par 2 correspond à la dérivée seconde de: a+bx+cx**2
+ 
+        // calcul des filtres 
+        filter_d0.d(a-rayon:a+rayon,a)=c(1,:)';
+        filter_d1.d(a-rayon:a+rayon,a)=c(2,:)';
+        filter_d2.d(a-rayon:a+rayon,a)=2*c(3,:)';
+    end;
+  
+
+    // ---------------------------------------------------
+    // calculs de Savitzsky-Golay sur les cotés du spectre
+    // --------------------------------------------------- 
+
+
+    // 1 - calcul le plus précis  
+
+    //d0 à gauche
+    calcul=saisir.d(:,1:2*rayon+1)*c'*m;
+    d0_savgol(:,1:rayon)=calcul(:,1:rayon);
+    //d0 à droite
+    calcul=saisir.d(:,p-2*rayon:p)*c'*m;
+    d0_savgol(:,p-rayon:p)=calcul(:,rayon+1:2*rayon+1);
+    
+    //d1 à gauche
+    d1=d0_savgol(:,2:p)-d0_savgol(:,1:p-1);
+    d1_savgol(:,1:rayon)=d1(:,1:rayon);
+    calcul=d1_savgol(:,1:2*rayon+1)*m'*inv(m*m')*m;
+    d1_savgol(:,1:rayon)=calcul(:,1:rayon);
+    //d1 à droite
+    d1_savgol(:,p-rayon:p)=d1(:,p-rayon-1:p-1);   //perte d'un indice à cause de la dérivée première
+    calcul=d1_savgol(:,p-2*rayon:p)*m'*inv(m*m')*m;
+    d1_savgol(:,p-rayon:p)=calcul(:,rayon+1:2*rayon+1);
+
+    //d2 à gauche
+    d2=d1_savgol(:,2:p-1)-d1_savgol(:,1:p-2);
+    d2_savgol(:,1:rayon)=d2(:,1:rayon);
+    calcul=d2_savgol(:,1:2*rayon+1)*m'*inv(m*m')*m;
+    d2_savgol(:,1:rayon)=calcul(:,1:rayon);
+    //d2 à droite
+    d2_savgol(:,p-rayon:p)=d2(:,p-rayon-2:p-2);   //perte de deux indices à cause de la dérivée seconde
+    calcul=d2_savgol(:,p-2*rayon:p)*m'*inv(m*m')*m;
+    d2_savgol(:,p-rayon:p)=calcul(:,rayon+1:2*rayon+1);
+
+
+//    // 2- calcul sous forme de filtres (+ généralisable mais moins précis)                    
+//    for i=1:rayon;
+//        mi=zeros(6,2*i+1); 
+//        vi=[-i:1:i];
+//        mi(1,:)=vi.^0;  
+//        mi(2,:)=vi.^1;  
+//        mi(3,:)=vi.^2;  
+//        mi(4,:)=vi.^3;  
+//        mi(5,:)=vi.^4;  
+//        mi(6,:)=vi.^5; 
+//        mi=mi(1:degre+1,:);  
+//        ci=inv(mi*mi')*mi;                                      //dimensions: (degre+1) x (2*rayon+1)
+//        filter_d0.d(1:2*i+1,i+1)=           ci(1,:)';           // à gauche
+//        filter_d0.d(p-(2*i+1)+1:p,p-i)=     ci(1,:)';           // à droite 
+//        filter_d1.d(1:2*i+1,i+1)=           ci(2,:)';           // à gauche
+//        filter_d1.d(p-(2*i+1)+1:p,p-i)=     ci(2,:)';           // à droite 
+//        filter_d2.d(1:2*i+1,i+1)=           2*ci(3,:)';         // à gauche
+//        filter_d2.d(p-(2*i+1)+1:p,p-i)=     2*ci(3,:)';         // à droite 
+//        if i==1 then
+//            filter_d0.d(1,1)=1;                                 // meilleur lissage pour 1 valeur = elle-même
+//            filter_d0.d(p,p)=1;
+//            filter_d1.d(1:2,1)=[-1;1];                          // on soustrait le 1° au 2° 
+//            filter_d1.d(p-1:p,p)=[-1;1];
+//            filter_d2.d(1:2*i+1,1)=         2*ci(3,:)';         // on recopie les valeurs à coté; pas trouvé mieux
+//            filter_d2.d(p-(2*i+1)+1:p,p)=   2*ci(3,:)';
+//        end
+//    end
+
+
+    //sélection des sorties       
+    if d012==0 then
+        res_savgol.d=d0_savgol;
+  //      filter_d012=filter_d0;
+    elseif d012==1 then 
+        res_savgol.d=d1_savgol;
+ //       filter_d012=filter_d1;
+    elseif d012==2 then
+        res_savgol.d=d2_savgol;
+ //       filter_d012=filter_d2;
+    end
+    
+    
+    // div
+    res_savgol.i=saisir.i;
+    res_savgol.v=saisir.v;
+    res_savgol=div(res_savgol);
+    
+//    filter_d012.i=saisir.v;
+//    filter_d012.v=saisir.v;
+//    filter_d012=div(filter_d012);
+    
+
+
+endfunction;
+
Binary file test-data/VI2016_AC_4Areduit_1.dat has changed
Binary file test-data/VI2016_AC_4Areduit_1.h5 has changed
Binary file test-data/VI2016_AC_4Areduit_1centroide.mat has changed