{fonction générales sur les spectres }
unit interpreteurSpectra;

interface

uses interpreteurBase;

const TailleMaxTrou=2048; { surface max des trous }
var
   ListeTx:array[1..1500,0..TailleMaxTrou] of word; { liste des trous de la matrice } { toutes les coordonnées X pour un trou }
   ListeTy:array[1..1500,0..TailleMaxTrou] of word;


    function addpt(par:parametresNum;pars:parametresStr):integer;
    function addpoint1D(par:parametresNum;pars:parametresStr):integer;
    function SetExpCond(par:parametresNum;pars:parametresStr):integer;
    function SetComment(par:parametresNum;pars:parametresStr):integer;
    function clearspectre(par:parametresNum;pars:parametresStr):integer;
    function addspectre(par:parametresNum;pars:parametresStr):integer;
    function Smooth1D(par:parametresNum;pars:parametresStr):integer;
    function Smooth2D(par:parametresNum;pars:parametresStr):integer;
    function DelSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function AddSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function SubSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function MultSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function DivSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function ScalAddSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function ScalSubSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function ScalMultSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function ScalDivSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function Sqrt1D(par:parametresNum;pars:parametresStr):integer;
    function Pos1D(par:parametresNum;pars:parametresStr):integer;
    function IntegraleSpectre1D(par:parametresNum;pars:parametresStr):integer;
    function DelSpectre2D(par:parametresNum;pars:parametresStr):integer;
    function AddSpectre2D(par:parametresNum;pars:parametresStr):integer;
    function SubSpectre2D(par:parametresNum;pars:parametresStr):integer;
    function MultSpectre2D(par:parametresNum;pars:parametresStr):integer;
    function DivSpectre2D(par:parametresNum;pars:parametresStr):integer;
    function ScalAddSpectre2D(par:parametresNum;pars:parametresStr):integer;
    function ScalSubSpectre2D(par:parametresNum;pars:parametresStr):integer;
    function ScalMultSpectre2D(par:parametresNum;pars:parametresStr):integer;
    function ScalDivSpectre2D(par:parametresNum;pars:parametresStr):integer;
  function Sqrt2D(par:parametresNum;pars:parametresStr):integer;
  function Pos2D(par:parametresNum;pars:parametresStr):integer;
  function IntegraleSpectre2D(par:parametresNum;pars:parametresStr):integer;
  function NormMoniSpectre2D(par:parametresNum;pars:parametresStr):integer;
  function ProjectionHSpectre2D(par:parametresNum;pars:parametresStr):integer;
  function ProjectionVSpectre2D(par:parametresNum;pars:parametresStr):integer;
  function SommeCirculaireSpectre2D(par:parametresNum;pars:parametresStr):integer;
  function SommeDNPA(par:parametresNum;pars:parametresStr):integer;
  function MasqueSecteur(par:parametresNum;pars:parametresStr):integer;
  function Barycentre2D(par:parametresNum;pars:parametresStr):integer;
  function concat1D(par:parametresNum;pars:parametresStr):integer;
  function concat2D(par:parametresNum;pars:parametresStr):integer;
  function Convert1Dto2Drow(par:parametresNum;pars:parametresStr):integer;
  function Convert1Dto2DrowY(par:parametresNum;pars:parametresStr):integer;
  function Convert1Dto2Dcol(par:parametresNum;pars:parametresStr):integer;
  function Convert1Dto2DcolX(par:parametresNum;pars:parametresStr):integer;
  function appendCol(par:parametresNum;pars:parametresStr):integer;
  function appendColX(par:parametresNum;pars:parametresStr):integer;
  function appendRow(par:parametresNum;pars:parametresStr):integer;
  function appendRowY(par:parametresNum;pars:parametresStr):integer;
  function resize1D(par:parametresNum;pars:parametresStr):integer;
  function extract1D(par:parametresNum;pars:parametresStr):integer;
  function extract2D(par:parametresNum;pars:parametresStr):integer;
  function SetX1D(par:parametresNum;pars:parametresStr):integer;
  function SetX2D(par:parametresNum;pars:parametresStr):integer;
  function SetY2D(par:parametresNum;pars:parametresStr):integer;

  function resample1D(par:parametresNum;pars:parametresStr):integer;
  function Resample(par:parametresNum;pars:parametresStr):integer;
  function Resample2D(par:parametresNum;pars:parametresStr):integer;
  function Remap2D_MSGC(par:parametresNum;pars:parametresStr):integer;
  function Remap2D_MSGC2(par:parametresNum;pars:parametresStr):integer;
  function Remap2DtoQxQz(par:parametresNum;pars:parametresStr):integer;
  function RemapToFdataToQxQz(par:parametresNum;pars:parametresStr):integer;
  function RemapTOFtoQxQz(par:parametresNum;pars:parametresStr):integer;
  function RemapTOFtoPiPf(par:parametresNum;pars:parametresStr):integer;
    
  function lineX(par:parametresNum;pars:parametresStr):integer;
  function lineY(par:parametresNum;pars:parametresStr):integer;
  function DelSpectre3D(par:parametresNum;pars:parametresStr):integer;
  function AddSpectre3D(par:parametresNum;pars:parametresStr):integer;
  function IntegraleSpectre3D(par:parametresNum;pars:parametresStr):integer;
  function Spectre3DTo2D(par:parametresNum;pars:parametresStr):integer;
  function FFT(par:parametresNum;pars:parametresStr):integer;
  function FFT2(par:parametresNum;pars:parametresStr):integer;
  function Module1D(par:parametresNum;pars:parametresStr):integer;
  function Module2D(par:parametresNum;pars:parametresStr):integer;
  function FlipUD(par:parametresNum;pars:parametresStr):integer; { flipping des data UP - DOWN }
  function FlipLR(par:parametresNum;pars:parametresStr):integer; { flipping des data UP - DOWN }
  function ConvertL2Q(par:parametresNum;pars:parametresStr):integer;
  function appendPSDdata(par:parametresNum;pars:parametresStr):integer;
  function threshold(par:parametresNum;pars:parametresStr):integer;
  function FindCentres(par:parametresNum;pars:parametresStr):integer;
  function FindCentres2(par:parametresNum;pars:parametresStr):integer;
  function FindCentres3(par:parametresNum;pars:parametresStr):integer;
  function SetTOFaxisLambda(par:parametresNum;pars:parametresStr):integer;
  function SetTOFaxisQz(par:parametresNum;pars:parametresStr):integer;
  function Raboutage(par:parametresNum;pars:parametresStr):integer;

implementation

uses Windows, MainForm, EditData, Math, Dialogs, sysUtils, interpreteur, boiteNoire, Graph2D, MtxVec, Math387;

{ ces fonctions sotn nécessaire parce qu'il y a une ambinguité des fonciotns min/max entre Math387 et MtxVec }
function maxi(a,b:double):double;
begin
   if a>b then maxi:=a else maxi:=b;
end;
function mini(a,b:double):double;
begin
   if a<b then mini:=a else mini:=b;
end;

{ ======================================================================= }
{fonction générales sur les spectres }

    {ajoute un point à un graph}
    {par[1]=1 ou 2 :dim
     pars[2] Nom du spectre
     par[3],par[4],par[5],par[6],par[7] : x,y,lt,z,mon}
    function addpt(par:parametresNum;pars:parametresStr):integer;
    begin
    if par[1]=1 then und.addpt(pars[2],par[3],par[4],par[5],par[6],par[7]);
    if par[1]=2 then deuxd.addpt(pars[2],par[3],par[4],par[5],par[6],par[7]);
    if par[1]=3 then troisd.addpt(pars[2],par[3],par[4],par[5],par[6],par[7]);
    result:=1;
    {$IFDEF PILOTAGE }
    {    sendmessage(principalform.handle,wm_redessine,0,0); }
    {$ENDIF }
    {$IFDEF TRAITEMENT }
    {sendmessage(TraitementMainForm.handle,wm_redessine,0,0);  }
    {$ENDIF }
    end;

    {ajoute un point à un spectre 1D}
    {pars[1] Nom du spectre
     par[2],par[3],par[4] : x,z,mon}
    function addpoint1D(par:parametresNum;pars:parametresStr):integer;
    begin
       und.addpt(pars[1],par[2],0,0,par[3],par[4]);
       result:=1;
       {$IFDEF PILOTAGE }
       sendmessage(principalform.handle,wm_redessine,0,0);
       {$ENDIF }
       {$IFDEF TRAITEMENT }
       {sendmessage(TraitementMainForm.handle,wm_redessine,0,0);  }
       {$ENDIF }
    end;


    {fonction permettant de modifier les conditions experimentalles d'un spectre
    INPUT par[1] 1:und ,2:deuxd, 3:3d
          pars[2]:nom du spectre
          pars[3]:nom de la condition experimentalle
          par[4]:valeur de la condition}
    function SetExpCond(par:parametresNum;pars:parametresStr):integer;
    var vind:integer;
    begin
    if par[1]=1 then
       begin
       vind:=und.indexof(pars[2]);
       if vind<>-1 then
       und.spect[vind].SetExpCond(pars[3],par[4]);
       end;
    if par[1]=2 then
       begin
       vind:=deuxd.indexof(pars[2]);
       if vind<>-1 then
       deuxd.spect[vind].SetExpCond(pars[3],par[4]);
       end;
    if par[1]=3 then
       begin
       vind:=troisd.indexof(pars[2]);
       if vind<>-1 then
       troisd.spect[vind].SetExpCond(pars[3],par[4]);
       end;
    end;

    {fonction permettant de modifier le commentaire d'un spectre
    INPUT par[1] 1:und ,2:deuxd, 3:3d
          pars[2]:nom du spectre
          pars[3],..,par[10]:commentaire}
    function SetComment(par:parametresNum;pars:parametresStr):integer;
    var vind:integer;
    begin
    if par[1]=1 then
       begin
       vind:=und.indexof(pars[2]);
       if vind<>-1 then
       und.spect[vind].comment:=pars[3]+pars[4]+pars[5]+pars[6]+pars[7]+pars[8]+pars[9]+pars[10];
       end;
    if par[1]=2 then
       begin
       vind:=deuxd.indexof(pars[2]);
       if vind<>-1 then
       deuxd.spect[vind].comment:=pars[3]+pars[4]+pars[5]+pars[6]+pars[7]+pars[8]+pars[9]+pars[10];
       end;
    if par[1]=3 then
       begin
       vind:=troisd.indexof(pars[2]);
       if vind<>-1 then
       troisd.spect[vind].comment:=pars[3]+pars[4]+pars[5]+pars[6]+pars[7]+pars[8]+pars[9]+pars[10];
       end;
    end;

    {mise a Zero d'un spectre}
    {par[1]=1,2,3 dim; pars[2] : nom du spectre}
    function clearspectre(par:parametresNum;pars:parametresStr):integer;
    begin
    if par[1]=1 then und.clear(pars[2]);
    if par[1]=2 then deuxd.clear(pars[2]);
    if par[1]=3 then troisd.clear(pars[2]);
    result:=1;
    end;
    {permet de créer un spectre en mémoire vive}
    {par[1] =1,2,3 Dim du spectre,
     pars[2] nom du spectre,
     par[3],par[4],par[5] dim X,Y,LT  }
    function addspectre(par:parametresNum;pars:parametresStr):integer;
    begin
    if par[1]=1 then und.addspectre(pars[2],round(par[3]),round(par[4]),round(par[5]));
    if par[1]=2 then deuxd.addspectre(pars[2],round(par[3]),round(par[4]),round(par[5]));
    if par[1]=3 then troisd.addspectre(pars[2],round(par[3]),round(par[4]),round(par[5]));
    result:=1;
    end;

    { lissage d'une courbe par moyenne glissante }
    { INPUT : pars[1] la courbe 1D a lisser     }
    {         pars [2] le nombre de points sur lesquels il faut moyenner }
    {         pars[3] la courbe de sorite       }
    { OUTPUT : pars[3] contient la courbe lissée }
    function Smooth1D(par:parametresNum;pars:parametresStr):integer;
    var i,j:integer;
        idx1,idx2,tailleX1:integer;
    begin
        idx1:=und.indexof(pars[1]);tailleX1:=und.spect[idx1].X;
        idx2:=und.addSpectre(pars[3],TailleX1,1,1);
        und.spect[idx2].typeX:=und.spect[idx1].typeX;
        for i:=0 to tailleX1-1 do
        begin
           und.spect[idx2].data[i,0,0].X:=und.spect[idx1].data[i,0,0].X;
           und.spect[idx2].data[i,0,0].Z:=und.spect[idx1].data[i,0,0].Z;
        end;
        for i:=round((par[2]-1)/2) to TailleX1-1-round((par[2]-1)/2) do
        begin
           und.spect[idx2].data[i,0,0].Z:=0;
           for j:=-round((par[2]-1)/2) to round((par[2]-1)/2) do
           begin
              und.spect[idx2].data[i,0,0].Z:=und.spect[idx2].data[i,0,0].Z+und.spect[idx1].data[i+j,0,0].Z;
           end;
           und.spect[idx2].data[i,0,0].Z:=und.spect[idx2].data[i,0,0].Z/par[2];
        end;
    end;

    { lissage d'une courbe par moyenne glissante }
    { INPUT : pars[1] la courbe 1D a lisser     }
    {         pars [2] le nombre de points sur lesquels il faut moyenner }
    {         pars[3] la courbe de sorite       }
    { OUTPUT : pars[3] contient la courbe lissée }
    function Smooth2D(par:parametresNum;pars:parametresStr):integer;
    var i,j,k,l:integer;
        idx1,idx2,tailleX1,tailleY1:integer;
    begin
        idx1:=deuxd.indexof(pars[1]);tailleX1:=deuxd.spect[idx1].X;tailleY1:=deuxd.spect[idx1].Y;
        idx2:=deuxd.addSpectre(pars[3],TailleX1,TailleY1,1);
        deuxd.spect[idx2].typeX:=deuxd.spect[idx1].typeX;
        deuxd.spect[idx2].typeY:=deuxd.spect[idx1].typeY;
        for i:=0 to tailleX1-1 do
          for j:=0 to tailleY1-1 do
          begin
            deuxd.spect[idx2].data[i,j,0].X:=deuxd.spect[idx1].data[i,j,0].X;
            deuxd.spect[idx2].data[i,j,0].Y:=deuxd.spect[idx1].data[i,j,0].Y;
            deuxd.spect[idx2].data[i,j,0].Z:=deuxd.spect[idx1].data[i,j,0].Z;
          end;
        for i:=round((par[2]-1)/2) to TailleX1-1-round((par[2]-1)/2) do
        for j:=round((par[2]-1)/2) to TailleY1-1-round((par[2]-1)/2) do
        begin
           deuxd.spect[idx2].data[i,j,0].Z:=0;
           for k:=-round((par[2]-1)/2) to round((par[2]-1)/2) do
           for l:=-round((par[2]-1)/2) to round((par[2]-1)/2) do
           begin
              deuxd.spect[idx2].data[i,j,0].Z:=deuxd.spect[idx2].data[i,j,0].Z+deuxd.spect[idx1].data[i+k,j+l,0].Z;
           end;
           deuxd.spect[idx2].data[i,j,0].Z:=deuxd.spect[idx2].data[i,j,0].Z/(par[2]*par[2]);
        end;
    end;

{ ======================================================================= }
{ ICI se trouvent les fonctions du script pour le traitement des spectres }
{ procédures agissant sur les spectres 1D }
    function DelSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
         und.delete(pars[1]);
    end;
    function AddSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
         und.addition(pars[1],pars[2],pars[3]);
    end;
    function SubSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
       und.soustraction(pars[1],pars[2],pars[3]);
    end;

    function MultSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
       und.multiplication(pars[1],pars[2],pars[3]);
    end;
    function DivSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
       und.division(pars[1],pars[2],pars[3]);
    end;
    function ScalAddSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
        und.ScalAdd(par[1],pars[2],pars[3]);
    end;
    function ScalSubSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
        und.ScalSub(par[1],pars[2],pars[3]);
    end;
    function ScalMultSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
        und.ScalMult(par[1],pars[2],pars[3]);
    end;
    function ScalDivSpectre1D(par:parametresNum;pars:parametresStr):integer;
    begin
        und.ScalDiv(par[1],pars[2],pars[3]);
    end;
    function Sqrt1D(par:parametresNum;pars:parametresStr):integer;
    begin
        und.SquareRoot(pars[1],pars[2]);
    end;
    { met toutes les valeurs negatives d'un spectre à zero, pour éviter d'avoir des neutrons "négatifs" après traitement }
    function Pos1D(par:parametresNum;pars:parametresStr):integer;
    begin
        deuxd.positif(pars[1],pars[2]);
    end;

    {integrale entre Xmin et Xmax
    pars[1] Nom1D
    par[2], par[3] xmin et xax  en Pixel si type raw ou absolue si une typeX<>raw
    par[4] nom variable parseur
    le résultat est stoké dans la boite noire
    ou dans la variable du parseur pars[4]si <>'' ex "var"}
    function IntegraleSpectre1D(par:parametresNum;pars:parametresStr):integer;
    var vind:integer;
        temp:double;
    begin
    vind:=und.indexof(pars[1]);
    if vind>0 then
       begin
       temp:=und.spect[vind].IntegraleSpectre1D(par[2],par[3]);
       if pars[4]<>'' then interpreteurform.parser1.setvariable(pars[6],temp)
       else  boitnoir.receivetext(floattostr(temp));
       end;
    end;

{ procédures agissant sur les spectres 2D }
    function DelSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
         deuxd.delete(pars[1]);
    end;
    function AddSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
         deuxd.addition(pars[1],pars[2],pars[3]);
    end;
    function SubSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
         deuxd.soustraction(pars[1],pars[2],pars[3]);
    end;
    function MultSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
       deuxd.multiplication(pars[1],pars[2],pars[3]);
    end;
    function DivSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
       deuxd.division(pars[1],pars[2],pars[3]);
    end;
    function ScalAddSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
        deuxd.ScalAdd(par[1],pars[2],pars[3]);
    end;
    function ScalSubSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
        deuxd.ScalSub(par[1],pars[2],pars[3]);
    end;
    function ScalMultSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
        deuxd.ScalMult(par[1],pars[2],pars[3]);
    end;
    function ScalDivSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
        deuxd.ScalDiv(par[1],pars[2],pars[3]);
    end;
    function Sqrt2D(par:parametresNum;pars:parametresStr):integer;
    begin
        deuxd.SquareRoot(pars[1],pars[2]);
    end;
    { met toutes les valuers negatives d'un spectre à zero, pour éviter d'avoir des neutrons "négatifs" après traitement }
    function Pos2D(par:parametresNum;pars:parametresStr):integer;
    begin
        deuxd.positif(pars[1],pars[2]);
    end;

    {integrale entre Xmin, ymin, Xmax, ymax
    pars[1] Nom2D
    par[2], par[3],par[4], par[5], xmin, ymin,xmax, ymax
    par[6] nom variable parseur
    le résultat est stoké dans la boite noire
    ou dans la variable du parseur pars[6]si <>'' ex "var"}
    function IntegraleSpectre2D(par:parametresNum;pars:parametresStr):integer;
    var vind:integer;
        temp:double;
    begin
    vind:=deuxd.indexof(pars[1]);
    if vind>0 then
       begin
       temp:=deuxd.spect[vind].IntegraleSpectre2D(par[2],par[3],par[4],par[5]);
       if pars[6]<>'' then interpreteurform.parser1.setvariable(pars[6],temp)
       else  boitnoir.receivetext(floattostr(temp));
       end;

    end;
    {Normalise le spectre à un moniteur de reference}
    {par[1]:moniteur de ref, Pars[2]: spectre ini; pars[3]:spectre normalisé}
    function NormMoniSpectre2D(par:parametresNum;pars:parametresStr):integer;
    begin
    interpreteurform.timer1.enabled:=false;
    if deuxd.indexof(pars[2])<>-1 then
       begin
       if deuxd.spect[deuxd.indexof(pars[2])].moniteur<>0 then
         begin
         deuxd.ScalMult(par[1]/deuxd.spect[deuxd.indexof(pars[2])].moniteur,pars[2],pars[3]);
         deuxd.spect[deuxd.indexof(pars[3])].moniteur:=par[1];
         {boitnoir.receivetext('normalisation :' + pars[2]+' moniteur ='+pars[1]);}
         end
       else
         boitnoir.receivetext('!! echec normalisation :' + pars[2]+' moniteur nul');
       end
    else
       boitnoir.receivetext('!! echec normalisation :' + pars[2]+' non trouvé');
    interpreteurform.timer1.enabled:=true;
    end;

{ fonctions de projection }
{ INPUT : pars[1], nom du spectre 2D}
{         par[2], ymin; par[3] ymax      }
{         pars[4], le nom du spectre 1D de sortie }
{ OUTPUT: le resultat est stocké dans le spectre unD 'pars[4]' }
{ A NOTER : pour l'utilisateur : projection verticale = projection SUR la direction verticale }
{           pour le programmeur (dans l'unité EditData), projection verticale = projection suivant la verticale }
    function ProjectionHSpectre2D(par:parametresNum;pars:parametresStr):integer;
    var vind:integer;
    begin
        vind:=deuxd.indexof(pars[1]);
        if vind>0 then unD.add(deuxd.spect[vind].ProjectionVSpectre2D(pars[4],par[2],par[3]));
    end;
    function ProjectionVSpectre2D(par:parametresNum;pars:parametresStr):integer;
    var vind:integer;
    begin
        vind:=deuxd.indexof(pars[1]);
        if vind>0 then unD.add(deuxd.spect[vind].ProjectionHSpectre2D(pars[4],par[2],par[3]));
    end;

    { INPUT : Pars[1]:nom du spectre 2D; pars[2]:nom du spectre 1D
    {         par[3],par[4]: X0, Y0 centre; par[5]: nombre de points (resolution)
    { OUTPUT: Spectre 1D pars[2]}
    function SommeCirculaireSpectre2D(par:parametresNum;pars:parametresStr):integer;
    var vind:integer;
    begin
        vind:=deuxd.indexof(pars[1]);
        if vind>0
        then unD.add(deuxd.spect[vind].SommeCirculaireSpectre2D(pars[2],par[3],par[4],par[5]));
    end;

    {fonction appellant une somme petits angles
    INPUT : Pars[1]:nom du spectre 2D; pars[2]:nom du spectre 1D
            pars[3]:nom du masque (si ce masque n'existe pas, le prg n'utilise pas de masquage
            par[4],par[5]: X0, Y0 centre; par[6]: nombre de points (resolution)
            par[7]: lambda (PAPOL :8); par[8] : delta Pixel en m (PAPOl : 0.005); par[9]: dist Ech/detect en m
    OUTPUT: Spectre 1D pars[2]}
    function SommeDNPA(par:parametresNum;pars:parametresStr):integer;
    begin
    interpreteurform.timer1.enabled:=false;
    if deuxd.indexof(pars[1])<>-1 then
       begin
       und.add(deuxd.spect[deuxd.indexof(pars[1])].SommePetitsAngles(pars[2],pars[3],par[4],par[5],par[6],par[7],par[8],par[9]));
       boitnoir.receivetext('Somme DNPA :' + pars[1]+' dans '+pars[2]);
       if deuxd.indexof(pars[3])<0 then boitnoir.receivetext('!!ATTENTION : masque ' + pars[3]+' non trouvé ');
       end
    else boitnoir.receivetext('!! echec Somme DNPA : ' + pars[1]+' non trouvé');
    interpreteurform.timer1.enabled:=true;
    end;

    {fonction multipliant le spectre deuxd.indexof(Pars[1]) par un secteur de 1 et 0 ailleurs}
    {Pars[1]:nom du spectre 2D;par[2],par[3]: X0, Y0 centre du secteur}
    {par[4]: angle median du secteur en convention geographique: 0 a midi, 90 a 3H, 180 a 6H, 270 a 9H  }
    {par[5]: angle total d'ouverture du secteur (plus ou moins thetaouv/2)}
    function MasqueSecteur(par:parametresNum;pars:parametresStr):integer;
    begin
    if deuxd.indexof(pars[1])<>-1 then
    deuxd.spect[deuxd.indexof(Pars[1])].MasqueSecteur(Par[2],Par[3],Par[4],Par[5],pars[6]);
    end;
    {Calcul le barycentre d'un spectre 2D afin de determiner le bean centre}
    {pars[1] : Nom du spectre 2D}
    function Barycentre2D(par:parametresNum;pars:parametresStr):integer;
    var vind,i,j:integer;
        X,Y,somme:double;
    begin
    vind:=deuxd.indexof(pars[1]);
    X:=0;Y:=0;somme:=0;
    if vind>0 then
      begin
      for i:=0 to deuxd.spect[vind].X-1 do
          for j:=0 to deuxd.spect[vind].Y-1 do
            begin
            X:=X+deuxd.spect[vind].data[i,j,0].z*i;
            Y:=Y+deuxd.spect[vind].data[i,j,0].z*j;
            somme:=somme+deuxd.spect[vind].data[i,j,0].z;
            end;
      if somme<>0 then
         begin
         X:=X/somme;Y:=Y/somme;
         end;
      boitnoir.receivetext('barycentre '+deuxd.spect[vind].nom+' : X0='+floattostr(X)+' Y0='+floattostr(Y));
      end;
    end;
    { fonction de concatenation de spectres 1D en un spectre 2D }
    { INPUT : pars[1], répertoire de lecture   }
    {         pars[2], nom de base des fichiers 1D }
    {         par[3], indice min, par[5], indice max }
    {         par[4], le step     }
    {         pars[6], extension des fichiers    }
    {         pars[7], nomdu spectre 2d de sortie, nom interne au programme }
    function concat1D(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i,imin,imax,j,ind,ind2D,longueurY:integer;
        s,s1:string;
    begin
       { lecture des fichiers 1D }
       imin:=round(par[3]);imax:=round(par[5]);
       interpreteurform.timer1.enabled:=false;
       { determination de la taille en Y }
       s:=pars[1]+pars[2]+intToStr(imin)+pars[6]; { nom complet du fichier }
       s1:=pars[2]+intToStr(round(imin))+pars[6]; { nom a donner au spectre }
       if editdata.fexis(s) then
       begin ind:=und.addspectre(s1,1,1,1); und.spect[ind].open(s) end
       else boitnoir.receivetext('!! echec ouverture : ' + s + ' n''existe pas');
       longueurY:=und.spect[ind].X;
       ind2D:=deuxd.addSpectre(pars[7],round((imax-imin)/par[4])+1,longueurY,1);
       deuxd.spect[ind2D].typeX:='raw';deuxd.spect[ind2D].typeY:='raw';

         i:=imin;
         while i<=imax do
         begin
             s:=pars[1]+pars[2]+intToStr(i)+pars[6]; { nom complet du fichier }
             s1:=pars[2]+intToStr(round(i))+pars[6]; { nom a donner au spectre }
             if editdata.fexis(s) then
             begin ind:=und.addspectre(s1,1,1,1); und.spect[ind].open(s);  end
             else boitnoir.receivetext('!! echec ouverture : ' + s + ' n''existe pas');
             { transfert dans le spectre 2D }
             for j:=0 to longueurY-1 do
             begin deuxd.spect[ind2D].data[round((i-imin)/par[4]),j,0].X:=i-imin;
                   deuxd.spect[ind2D].data[round((i-imin)/par[4]),j,0].Y:=j;
                   deuxd.spect[ind2D].data[round((i-imin)/par[4]),j,0].Z:=und.spect[ind].data[j,0,0].z;
                   end;
             und.delete(s1);
             i:=i+round(par[4]);
         end;
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction de concatenation de deux spectres spectres 2D en un spectre 2D }
    { INPUT : pars[1], nom du premier spectre   }
    {         pars[2], nom du deuxième spectre }
    {         par[3], nom du spectre de sortie }
    { NOTA : il faut que les steps et les unités des deux spectres soient les memes  }
    function concat2D(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i,imin,imax,j,ind,ind2D,longueurY:integer;
        idx1,idx2,idx3:integer;
        xmin1,xmax1,ymin1,ymax1,xstep1,ystep1:double;
        xmin2,xmax2,ymin2,ymax2,xstep2,ystep2:double;
        xmin3,xmax3,ymin3,ymax3,xstep3,ystep3:double;
        tailleX1,TailleX2,TailleX3,tailleY1,tailleY2,tailleY3:integer;
        xaux,yaux,zaux:double;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=deuxd.indexof(pars[1]);idx2:=deuxd.indexof(pars[2]);
       tailleX1:=deuxd.spect[idx1].X;tailleX2:=deuxd.spect[idx2].X;
       tailleY1:=deuxd.spect[idx1].Y;tailleY2:=deuxd.spect[idx2].Y;
       Xmin1:=deuxd.spect[idx1].data[0,0,0].X;Ymin1:=deuxd.spect[idx1].data[0,0,0].Y;
       Xmax1:=deuxd.spect[idx1].data[tailleX1-1,tailleY1-1,0].X;Ymax1:=deuxd.spect[idx1].data[tailleX1-1,tailleY1-1,0].Y;
       if tailleX1<>1 then Xstep1:=(Xmax1-Xmin1)/(tailleX1-1) else Xstep1:=1;
       if tailleY1<>1 then Ystep1:=(Ymax1-Ymin1)/(tailleY1-1) else Ystep1:=1;
       Xmin2:=deuxd.spect[idx2].data[0,0,0].X;Ymin2:=deuxd.spect[idx2].data[0,0,0].Y;
       Xmax2:=deuxd.spect[idx2].data[tailleX2-1,tailleY2-1,0].X;Ymax2:=deuxd.spect[idx2].data[tailleX2-1,tailleY2-1,0].Y;
       if tailleX2<>1 then Xstep2:=(Xmax2-Xmin2)/(tailleX2-1) else Xstep2:=1;
       if tailleY2<>1 then Ystep2:=(Ymax2-Ymin2)/(tailleY2-1) else Ystep2:=1;
       { verification de la compatibilité des spectres }
       if (deuxd.spect[idx1].typeX<>deuxd.spect[idx2].typeX)
       then MessageDlg('X coordinate types not compatible',mtError,[mbOk],0);
       if (deuxd.spect[idx1].typeY<>deuxd.spect[idx2].typeY)
       then MessageDlg('Y coordinate types not compatible',mtError,[mbOk],0);
       if abs(Xstep1-Xstep2)>1e-8 then MessageDlg('X step sizes not compatible',mtError,[mbOk],0);
       if abs(Ystep1-Ystep2)>1e-8 then MessageDlg('Y step sizes not compatible',mtError,[mbOk],0);
       { determination de la taille du nouveau spectre et initialisation }
       Xmin3:=mini(Xmin1,Xmin2);Ymin3:=mini(Ymin1,Ymin2);
       Xmax3:=maxi(Xmax1,Xmax2);Ymax3:=maxi(Ymax1,Ymax2);
       Xstep3:=Xstep1;Ystep3:=Ystep1;
       TailleX3:=round((Xmax3-Xmin3)/XStep3+1);TailleY3:=round((Ymax3-Ymin3)/YStep3+1);
       idx3:=deuxd.addSpectre(pars[3],TailleX3,TailleY3,1);
       deuxd.spect[idx3].typeX:=deuxd.spect[idx1].typeX;deuxd.spect[idx3].typeY:=deuxd.spect[idx1].typeY;
       { remplissage du nouveau spectre }
       { scan du premier spectre }
       for i:=0 to TailleX1-1 do
        for j:=0 to TailleY1-1 do
          begin
            xaux:=deuxd.spect[idx1].data[i,j,0].x;
            yaux:=deuxd.spect[idx1].data[i,j,0].y;
            zaux:=deuxd.spect[idx1].data[i,j,0].z;
            deuxd.spect[idx3].data[round((xaux-xmin3)/xstep1),round((yaux-ymin3)/ystep1),0].X:=xaux;
            deuxd.spect[idx3].data[round((xaux-xmin3)/xstep1),round((yaux-ymin3)/ystep1),0].Y:=yaux;
            deuxd.spect[idx3].data[round((xaux-xmin3)/xstep1),round((yaux-ymin3)/ystep1),0].Z:=zaux;
          end;
       { scan du deuxième spectre }
       for i:=0 to TailleX2-1 do
        for j:=0 to TailleY2-1 do
          begin
            xaux:=deuxd.spect[idx2].data[i,j,0].x;
            yaux:=deuxd.spect[idx2].data[i,j,0].y;
            zaux:=deuxd.spect[idx2].data[i,j,0].z;
            deuxd.spect[idx3].data[round((xaux-xmin3)/xstep1),round((yaux-ymin3)/ystep1),0].X:=xaux;
            deuxd.spect[idx3].data[round((xaux-xmin3)/xstep1),round((yaux-ymin3)/ystep1),0].Y:=yaux;
            deuxd.spect[idx3].data[round((xaux-xmin3)/xstep1),round((yaux-ymin3)/ystep1),0].Z:=zaux;
          end;
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction de transfert d'un spectre 1D vers 2D ; vital pour les fonctions Append }
    { INPUT : pars[1], nom du spectre 2D  }
    {         pars[2], nom du spectre 1D}
    { NOTA : il faut que la taille du spectre 1D soit compatoble à 2D.tailleY }
    {        pour le moment, ca suppose que le type est 'raw'                 }
    function Convert1Dto2Drow(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i:integer;
        idx1,idx2:integer;
        tailleX1:integer;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=und.indexof(pars[1]);
       tailleX1:=und.spect[idx1].X;
       { determination de la taille du nouveau spectre et initialisation }
       { **********  OPERATION STRICTEMENT ILLEGALE ************* }
       { redomensionnement du spectres ; on a beauc<oup de chances de perdre des data }
       idx2:=deuxd.addSpectre(pars[2],TailleX1,1,1);
       deuxd.spect[idx2].typeX:=und.spect[idx2].typeX;
       deuxd.spect[idx2].typeY:='raw';
       { remplissage de la colonne supplémentaire }
       { scan du premier spectre }
       for i:=0 to TailleX1-1 do
         begin  deuxd.spect[idx2].data[i,0,0].X:=und.spect[idx1].data[i,0,0].X;
                deuxd.spect[idx2].data[i,0,0].Y:=0;
                deuxd.spect[idx2].data[i,0,0].Z:=und.spect[idx1].data[i,0,0].Z end;
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction de transfert d'un spectre 1D vers 2D avec entree de y; vital pour les fonctions Append }
    { INPUT : pars[1], nom du spectre 1D}
    {         pars[2], nom du spectre 2D}
    {         pars[3], y0               }
    {         pars[4], type des oronnées        }
    { NOTA : il faut que la taille du spectre 1D soit compatoble à 2D.tailleY }
    {        pour le moment, ca suppose que le type est 'raw'                 }
    function Convert1Dto2DrowY(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i:integer;
        idx1,idx2:integer;
        tailleX1:integer;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=und.indexof(pars[1]);
       tailleX1:=und.spect[idx1].X;
       { determination de la taille du nouveau spectre et initialisation }
       { **********  OPERATION STRICTEMENT ILLEGALE ************* }
       { redomensionnement du spectres ; on a beauc<oup de chances de perdre des data }
       idx2:=deuxd.addSpectre(pars[2],TailleX1,1,1);
       deuxd.spect[idx2].typeX:=und.spect[idx2].typeX;
       deuxd.spect[idx2].typeY:=pars[4];
       { remplissage de la colonne supplémentaire }
       { scan du premier spectre }
       for i:=0 to TailleX1-1 do
         begin  deuxd.spect[idx2].data[i,0,0].X:=und.spect[idx1].data[i,0,0].X;
                deuxd.spect[idx2].data[i,0,0].Y:=par[3];
                deuxd.spect[idx2].data[i,0,0].Z:=und.spect[idx1].data[i,0,0].Z end;
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction de transfert d'un spectre 1D vers 2D ; vital pour les fonctions Append }
    { INPUT : pars[1], nom du spectre 2D  }
    {         pars[2], nom du spectre 1D}
    { NOTA : il faut que la taille du spectre 1D soit compatoble à 2D.tailleY }
    {        pour le moment, ca suppose que le type est 'raw'                 }
    function Convert1Dto2Dcol(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i:integer;
        idx1,idx2:integer;
        tailleX1:integer;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=und.indexof(pars[1]);
       tailleX1:=und.spect[idx1].X;
       { determination de la taille du nouveau spectre et initialisation }
       { **********  OPERATION STRICTEMENT ILLEGALE ************* }
       { redomensionnement du spectres ; on a beauc<oup de chances de perdre des data }
       idx2:=deuxd.addSpectre(pars[2],1,TailleX1,1);
       deuxd.spect[idx2].typeX:='raw';
       deuxd.spect[idx2].typeY:=und.spect[idx2].typeX;
       { remplissage de la colonne supplémentaire }
       { scan du premier spectre }
       for i:=0 to TailleX1-1 do
         begin  deuxd.spect[idx2].data[0,i,0].X:=0;
                deuxd.spect[idx2].data[0,i,0].Y:=und.spect[idx1].data[i,0,0].X;
                deuxd.spect[idx2].data[0,i,0].Z:=und.spect[idx1].data[i,0,0].Z end;
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction de transfert d'un spectre 1D vers 2D ; vital pour les fonctions Append }
    { INPUT : pars[1], nom du spectre 2D  }
    {         pars[2], nom du spectre 1D}
    {         par[3], valeur de l'abscisse                     }
    {         pars[4], type des abscisses        }
    { NOTA : il faut que la taille du spectre 1D soit compatoble à 2D.tailleY }
    {        pour le moment, ca suppose que le type est 'raw'                 }
    function Convert1Dto2DcolX(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i:integer;
        idx1,idx2:integer;
        tailleX1:integer;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=und.indexof(pars[1]);
       tailleX1:=und.spect[idx1].X;
       { determination de la taille du nouveau spectre et initialisation }
       { **********  OPERATION STRICTEMENT ILLEGALE ************* }
       { redomensionnement du spectres ; on a beauc<oup de chances de perdre des data }
       idx2:=deuxd.addSpectre(pars[2],1,TailleX1,1);
       deuxd.spect[idx2].typeX:=pars[4];
       deuxd.spect[idx2].typeY:=und.spect[idx2].typeX;
       { remplissage de la colonne supplémentaire }
       { scan du premier spectre }
       for i:=0 to TailleX1-1 do
         begin  deuxd.spect[idx2].data[i,0,0].X:=par[3];
                deuxd.spect[idx2].data[0,i,0].Y:=und.spect[idx1].data[i,0,0].X;
                deuxd.spect[idx2].data[0,i,0].Z:=und.spect[idx1].data[i,0,0].Z end;
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction d'append d'un spectre 1D à un spectre 2D }
    { INPUT : pars[1], nom du spectre 2D  }
    {         pars[2], nom du spectre 1D}
    { NOTA : il faut que la taille du spectre 1D soit compatoble à 2D.tailleY }
    {        pour le moment, ca suppose que le type est 'raw'                 }
    function appendCol(par:parametresNum;pars:parametresStr):integer;
    var i,j:integer;
        idx1,idx2,idx3:integer;
        tailleX1,TailleX2,tailleY1,tailleY2:integer;
        zaux:double;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=deuxd.indexof(pars[1]);idx2:=und.indexof(pars[2]);
       tailleX1:=deuxd.spect[idx1].X;tailleY1:=deuxd.spect[idx1].Y;tailleX2:=und.spect[idx2].X;
       { verification de la compatibilité des spectres }
       if (tailleY1<>tailleX2) then MessageDlg('Spectra sizes are not compatible!',mtError,[mbOk],0);
       { determination de la taille du nouveau spectre et initialisation }
       { **********  OPERATION STRICTEMENT ILLEGALE ************* }
       { redomensionnement du spectres ; on a beauc<oup de chances de perdre des data }
       idx3:=deuxd.addSpectre(pars[1]+'.TMP',TailleX1+1,TailleY1,1);
       deuxd.spect[idx3].typeX:='raw';deuxd.spect[idx3].typeY:='raw';
       { remplissage de la colonne supplémentaire }
       { scan du premier spectre }
       for i:=0 to TailleX1-1 do
         for j:=0 to TailleY1-1 do
         begin  deuxd.spect[idx3].data[i,j,0].X:=deuxd.spect[idx1].data[i,j,0].X;
                deuxd.spect[idx3].data[i,j,0].Y:=deuxd.spect[idx1].data[i,j,0].Y;
                deuxd.spect[idx3].data[i,j,0].Z:=deuxd.spect[idx1].data[i,j,0].Z;
         end;
       for j:=0 to TailleY1-1 do
          begin
            zaux:=und.spect[idx2].data[j,0,0].z;
            deuxd.spect[idx3].data[tailleX1,j,0].X:=tailleX1;
            deuxd.spect[idx3].data[tailleX1,j,0].Y:=und.spect[idx2].data[j,0,0].Y;
            deuxd.spect[idx3].data[tailleX1,j,0].Z:=zaux;
          end;
       deuxd.deletespectre(idx1);
       deuxd.spect[idx3].Nom:=pars[1];
       interpreteurform.timer1.enabled:=true;
    end;

        { fonction d'append d'un spectre 1D à un spectre 2D }
    { INPUT : pars[1], nom du spectre 2D  }
    {         pars[2], nom du spectre 1D}
    {         par[3], la valeur de l'abscisse          }
    { NOTA : il faut que la taille du spectre 1D soit compatoble à 2D.tailleY }
    {        pour le moment, ca suppose que le type est 'raw'                 }
    function appendColX(par:parametresNum;pars:parametresStr):integer;
    var i,j:integer;
        idx1,idx2,idx3:integer;
        tailleX1,TailleX2,tailleY1,tailleY2:integer;
        zaux:double;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=deuxd.indexof(pars[1]);idx2:=und.indexof(pars[2]);
       tailleX1:=deuxd.spect[idx1].X;tailleY1:=deuxd.spect[idx1].Y;tailleX2:=und.spect[idx2].X;
       { verification de la compatibilité des spectres }
       if (tailleY1<>tailleX2) then MessageDlg('Spectra sizes are not compatible!',mtError,[mbOk],0);
       { determination de la taille du nouveau spectre et initialisation }
       { **********  OPERATION STRICTEMENT ILLEGALE ************* }
       { redomensionnement du spectres ; on a beauc<oup de chances de perdre des data }
       idx3:=deuxd.addSpectre(pars[1]+'.TMP',TailleX1+1,TailleY1,1);
       deuxd.spect[idx3].typeX:='raw';deuxd.spect[idx3].typeY:='raw';
       { remplissage de la colonne supplémentaire }
       { scan du premier spectre }
       for i:=0 to TailleX1-1 do
         for j:=0 to TailleY1-1 do
         begin  deuxd.spect[idx3].data[i,j,0].X:=deuxd.spect[idx1].data[i,j,0].X;
                deuxd.spect[idx3].data[i,j,0].Y:=deuxd.spect[idx1].data[i,j,0].Y;
                deuxd.spect[idx3].data[i,j,0].Z:=deuxd.spect[idx1].data[i,j,0].Z;
         end;
       for j:=0 to TailleY1-1 do
          begin
            zaux:=und.spect[idx2].data[j,0,0].z;
            deuxd.spect[idx3].data[tailleX1,j,0].X:=par[3];
            deuxd.spect[idx3].data[tailleX1,j,0].Y:=und.spect[idx2].data[j,0,0].Y;
            deuxd.spect[idx3].data[tailleX1,j,0].Z:=zaux;
          end;
       deuxd.deletespectre(idx1);
       deuxd.spect[idx3].Nom:=pars[1];
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction d'append d'un spectre 1D à un spectre 2D }
    { INPUT : pars[1], nom du spectre 2D  }
    {         pars[2], nom du spectre 1D}
    { NOTA : il faut que la taille du spectre 1D soit compatoble à 2D.tailleY }
    {        pour le moment, ca suppose que le type est 'raw'                 }
    function appendRow(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i,imin,imax,j,ind,ind2D,longueurY:integer;
        idx1,idx2,idx3:integer;
        tailleX1,TailleX2,TailleX3,tailleY1,tailleY2,tailleY3:integer;
        xaux,yaux,zaux:double;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=deuxd.indexof(pars[1]);idx2:=und.indexof(pars[2]);
       tailleX1:=deuxd.spect[idx1].X;tailleY1:=deuxd.spect[idx1].Y;tailleX2:=und.spect[idx2].X;
       { verification de la compatibilité des spectres }
       if (tailleX1<>tailleX2) then MessageDlg('Spectra sizes are not compatible!',mtError,[mbOk],0);
       { determination de la taille du nouveau spectre et initialisation }
       { **********  OPERATION STRICTEMENT ILLEGALE ************* }
       { redomensionnement du spectres ; on a beauc<oup de chances de perdre des data }
       idx3:=deuxd.addSpectre(pars[1]+'.TMP',TailleX1,TailleY1+1,1);
       deuxd.spect[idx3].typeX:='raw';deuxd.spect[idx3].typeY:='raw';
       { remplissage de la colonne supplémentaire }
       { scan du premier spectre }
       { recopie du spectre précédent }
       for i:=0 to TailleX1-1 do
         for j:=0 to TailleY1-1 do
         begin  deuxd.spect[idx3].data[i,j,0].X:=deuxd.spect[idx1].data[i,j,0].X;
                deuxd.spect[idx3].data[i,j,0].Y:=deuxd.spect[idx1].data[i,j,0].Y;
                deuxd.spect[idx3].data[i,j,0].Z:=deuxd.spect[idx1].data[i,j,0].Z;
         end;
       for j:=0 to TailleX1-1 do
          begin
            zaux:=und.spect[idx2].data[j,0,0].z;
            {deuxd.spect[idx3].data[j,tailleY1,0].X:=j;}
            deuxd.spect[idx3].data[j,tailleY1,0].X:=und.spect[idx2].data[j,0,0].X;
            deuxd.spect[idx3].data[j,tailleY1,0].Y:=tailleY1;
            deuxd.spect[idx3].data[j,tailleY1,0].Z:=zaux;
          end;

       deuxd.deletespectre(idx1);
       deuxd.spect[idx3].Nom:=pars[1];
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction d'append d'un spectre 1D à un spectre 2D avec determination de Y}
    { INPUT : pars[1], nom du spectre 2D}
    {         pars[2], nom du spectre 1D}
    {         pars[3], y0               }
    { NOTA : il faut que la taille du spectre 1D soit compatoble à 2D.tailleY }
    {        pour le moment, ca suppose que le type est 'raw'                 }
    function appendRowY(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i,imin,imax,j,ind,ind2D,longueurY:integer;
        idx1,idx2,idx3:integer;
        tailleX1,TailleX2,TailleX3,tailleY1,tailleY2,tailleY3:integer;
        xaux,yaux,zaux:double;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=deuxd.indexof(pars[1]);idx2:=und.indexof(pars[2]);
       tailleX1:=deuxd.spect[idx1].X;tailleY1:=deuxd.spect[idx1].Y;tailleX2:=und.spect[idx2].X;
       { verification de la compatibilité des spectres }
       if (tailleX1<>tailleX2) then MessageDlg('Spectra sizes are not compatible!',mtError,[mbOk],0);
       { determination de la taille du nouveau spectre et initialisation }
       { **********  OPERATION STRICTEMENT ILLEGALE ************* }
       { redomensionnement du spectres ; on a beauc<oup de chances de perdre des data }
       idx3:=deuxd.addSpectre(pars[1]+'.TMP',TailleX1,TailleY1+1,1);
       {deuxd.spect[idx3].typeX:='raw'};deuxd.spect[idx3].typeY:='raw';
       deuxd.spect[idx3].typeX:=und.spect[idx1].typeX;
       { remplissage de la colonne supplémentaire }
       { scan du premier spectre }
       { recopie du spectre précédent }
       for i:=0 to TailleX1-1 do
         for j:=0 to TailleY1-1 do
         begin  deuxd.spect[idx3].data[i,j,0].X:=deuxd.spect[idx1].data[i,j,0].X;
                deuxd.spect[idx3].data[i,j,0].Y:=deuxd.spect[idx1].data[i,j,0].Y;
                deuxd.spect[idx3].data[i,j,0].Z:=deuxd.spect[idx1].data[i,j,0].Z;
         end;
       for j:=0 to TailleX1-1 do
          begin
            zaux:=und.spect[idx2].data[j,0,0].z;
            {deuxd.spect[idx3].data[j,tailleY1,0].X:=j;}
            deuxd.spect[idx3].data[j,tailleY1,0].X:=und.spect[idx2].data[j,0,0].X;
            deuxd.spect[idx3].data[j,tailleY1,0].Y:=par[3];
            deuxd.spect[idx3].data[j,tailleY1,0].Z:=zaux;
          end;
       deuxd.deletespectre(idx1);
       deuxd.spect[idx3].Nom:=pars[1];
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction de redimmension d'un spectre 1D}
    { INPUT : pars[1], nom du spectre 1D #1     }
    {         pars[2], xmin                     }
    {         pars[3], xmax                     }
    {         pars[4], nom du spectre 1D #2     }
    function resize1D(par:parametresNum;pars:parametresStr):integer;
    var fich:text;
        i,j:integer;
        idx1,idx2:integer;
        tailleX1,TailleX2:integer;
        xmin,xmax,xstep,x0,xN:double;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=und.indexof(pars[1]);
       tailleX1:=und.spect[idx1].X;
       { determination de la taille du nouveau spectre et initialisation }
       Xmin:=par[2];
       Xmax:=par[3];
       {x0 premier point du fichier 1D, xN dernier point}
       X0:=und.spect[idx1].data[0,0,0].X;
       XN:=und.spect[idx1].data[tailleX1-1,0,0].X;
       Xstep:=(XN-X0)/(tailleX1-1);
       {creation du nouveau spectre 1D}
       TailleX2:=round((Xmax-Xmin)/Xstep)+1;
       idx2:=und.addSpectre(pars[4],TailleX2,1,1);
       und.spect[idx2].typeX:=und.spect[idx1].typeX;
       und.spect[idx1].typeY:='raw';
       j:=0;
       for i:=0 to TailleX2-1 do
         begin
         und.spect[idx2].data[i,0,0].X:=Xmin+i*Xstep;
         und.spect[idx2].data[i,0,0].Y:=0;
         if und.spect[idx2].data[i,0,0].X<X0 then
                begin
                und.spect[idx2].data[i,0,0].Z:=0;
                inc(j);
                end;
         if (und.spect[idx2].data[i,0,0].X>=X0) and (und.spect[idx2].data[i,0,0].X<=XN) then und.spect[idx2].data[i,0,0].Z:=und.spect[idx1].data[i-j,0,0].Z;
         if und.spect[idx2].data[i,0,0].X>=XN then und.spect[idx2].data[i,0,0].Z:=0;
         end;

       und.spect[idx2].Nom:=pars[4];
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction de reéchantillonnage d'un spectre 1D  }
    { INPUT : pars[1], nom du spectre                }
    {         pars[2], pas du nouvel échantillonnage }
    {         par[3], nom du spectre de sortie       }
    { NOTE : le pas du nouvel échantillonage peut etre quelconque ; SUPERIEUR au pas initial !}
    { ne fonctionne que si les x sont ordonnés dans le bon sens ! }
    function resample1D(par:parametresNum;pars:parametresStr):integer;
    var i,j,imin,imax:integer;
        tailleX1,tailleX2,idx1,idx2:integer;
        somme,xmin1,xmax1,xstep1,xstep2,x2,x2m,x2p:double;
        finished:boolean;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=und.indexof(pars[1]);
       imin:=0;imax:=und.spect[idx1].X-1;
       xmin1:=und.spect[idx1].data[imin,0,0].X;xmax1:=und.spect[idx1].data[imax,0,0].X;
       xstep1:=(xmax1-xmin1)/(imax);  { actual sampling step }
       xstep2:=par[2]; { new sampling step }
       {creation du nouveau spectre 1D}
       TailleX2:=round((Xmax1-Xmin1)/Xstep2);
       idx2:=und.addSpectre(pars[3],TailleX2,1,1);
       und.spect[idx2].typeX:=und.spect[idx1].typeX;
       und.spect[idx2].typeY:='raw';
       { remplissage du nouveau spectre }
       for i:=0 to TailleX2-1 do
         begin
         j:=0;
         { remplissage de la nouvelle abscisse }
         x2:=Xmin1+i*Xstep2;
         und.spect[idx2].data[i,0,0].X:=x2;
         und.spect[idx2].data[i,0,0].Y:=0;
         { remplissage de l'ordonnée }
         { on intègre la fonction initiale entre x2m = x2-Xstep2/2 et x2p = x2+Xstep2/2 }
         somme:=0;j:=0;
         x2m:=x2-Xstep2/2;x2p:=x2+Xstep2/2;
         { on incrémente j jusqu'à qu'on rentre dans un intervalle intéressant de la fonction initiale }
         while und.spect[idx1].data[j,0,0].X<=x2m do inc(j);
         { intégration à "gauche" du premier point de la fonction initiale dans l'intervalle }
         somme:=somme+und.spect[idx1].data[j,0,0].Z*(und.spect[idx1].data[j,0,0].X-X2m)/xstep1;
         finished:=false;
         while not(finished) do
         begin
            if (und.spect[idx1].data[j,0,0].X+Xstep1)<X2p
            then begin somme:=somme+und.spect[idx1].data[j,0,0].Z*0.5;inc(j);
                       somme:=somme+und.spect[idx1].data[j,0,0].Z*0.5; end
            else begin somme:=somme+und.spect[idx1].data[j,0,0].Z*(X2p-und.spect[idx1].data[j,0,0].X)/xstep1;finished:=true end;
         end;
         und.spect[idx2].data[i,0,0].Z:=somme;
         end;
       und.spect[idx2].Nom:=pars[3];
       interpreteurform.timer1.enabled:=true;
    end;


    { fonction de redimensionnement d'un spectre 2D     }
    { INPUT : pars[1], nom du premier spectre           }
    {         pars[2], xmin; pars[3], xmax;  }
    {         par[4], nom du spectre de sortie }
    function extract1D(par:parametresNum;pars:parametresStr):integer;
    var i,j:integer;
        tailleX1,tailleX2,idx1,idx2:integer;
        xmin1,xmax1,xstep1,xaux,zaux:double;
    begin
       interpreteurform.timer1.enabled:=false;
       { soit a determiner la taille du spectre de sortie }
       idx1:=und.indexof(pars[1]);
       tailleX1:=und.spect[idx1].X;
       Xmin1:=und.spect[idx1].data[0,0,0].X;
       Xmax1:=und.spect[idx1].data[tailleX1-1,0,0].X;
       Xstep1:=(Xmax1-Xmin1)/(tailleX1-1);
       { creation du nouveau spectre }
       tailleX2:=round((par[3]-par[2])/XStep1+1);
       { determination de la taille du nouveau spectre et initialisation }
       idx2:=und.addSpectre(pars[4],TailleX2,1,1);
       und.spect[idx2].typeX:=und.spect[idx1].typeX;
       { remplissage du nouveau spectre }  { scan du premier spectre }
       for i:=0 to TailleX1-1 do
          begin
            xaux:=und.spect[idx1].data[i,0,0].x;
            zaux:=und.spect[idx1].data[i,0,0].z;
            if (xaux>=par[2]) and (xaux<=par[3]) then
            begin
            und.spect[idx2].data[round((xaux-par[2])/xstep1),0,0].X:=xaux;
            und.spect[idx2].data[round((xaux-par[2])/xstep1),0,0].Z:=zaux;
            end;
          end;
       interpreteurform.timer1.enabled:=true;
    end;

    { fonction de redimensionnement d'un spectre 2D     }
    { INPUT : pars[1], nom du premier spectre           }
    {         pars[2], xmin; pars[3], xmax; pars[4],ymin; pars[5], ymax }
    {         par[6], nom du spectre de sortie }
    { A NOTER : pour eviter les "lignes blanches" il vaut mieux que les bornes correspondent }
    {           à des valeurs des axes X et Y                                   }
    function extract2D(par:parametresNum;pars:parametresStr):integer;
    var i,j:integer;
        tailleX1,tailleY1,tailleX2,tailleY2,idx1,idx2:integer;
        xmin1,xmax1,ymin1,ymax1,xstep1,ystep1,xaux,yaux,zaux:double;
        xmin_e,xmax_e,ymin_e,ymax_e,x1,x2,y1,y2:double;
    begin
       { soit a determiner la taille du spectre de sortie }
       idx1:=deuxd.indexof(pars[1]);
       tailleX1:=deuxd.spect[idx1].X;tailleY1:=deuxd.spect[idx1].Y;
       Xmin1:=mini(deuxd.spect[idx1].data[0,0,0].X,deuxd.spect[idx1].data[tailleX1-1,tailleY1-1,0].X);
       Xmax1:=maxi(deuxd.spect[idx1].data[0,0,0].X,deuxd.spect[idx1].data[tailleX1-1,tailleY1-1,0].X);
       Ymin1:=mini(deuxd.spect[idx1].data[0,0,0].Y,deuxd.spect[idx1].data[tailleX1-1,tailleY1-1,0].Y);
       Ymax1:=maxi(deuxd.spect[idx1].data[0,0,0].Y,deuxd.spect[idx1].data[tailleX1-1,tailleY1-1,0].Y);
       Xstep1:=(Xmax1-Xmin1)/(tailleX1-1);Ystep1:=(Ymax1-Ymin1)/(tailleY1-1);
       { creation du nouveau spectre } { on détermine les poinsts extremes }
       X1:=deuxd.spect[idx1].data[trunc((par[2]-Xmin1)/Xstep1),0,0].X;
       Y1:=deuxd.spect[idx1].data[0,trunc((par[4]-Ymin1)/Ystep1),0].Y;
       X2:=deuxd.spect[idx1].data[trunc((par[3]-Xmin1)/Xstep1),0,0].X;
       Y2:=deuxd.spect[idx1].data[0,trunc((par[5]-Ymin1)/Ystep1),0].Y;
       xmin_e:=mini(X1,X2);xmax_e:=maxi(X1,X2);
       ymin_e:=mini(Y1,Y2);ymax_e:=maxi(Y1,Y2);
       tailleX2:=round((xmax_e-xmin_e)/XStep1+1);
       tailleY2:=round((ymax_e-ymin_e)/YStep1+1);
       { determination de la taille du nouveau spectre et initialisation }
       idx2:=deuxd.addSpectre(pars[6],TailleX2,TailleY2,1);
       deuxd.spect[idx2].typeX:=deuxd.spect[idx1].typeX;deuxd.spect[idx2].typeY:=deuxd.spect[idx1].typeY;
       { remplissage du nouveau spectre }
       { scan du premier spectre }
       for i:=0 to TailleX1-1 do
        for j:=0 to TailleY1-1 do
          begin
            xaux:=deuxd.spect[idx1].data[i,j,0].x;
            yaux:=deuxd.spect[idx1].data[i,j,0].y;
            zaux:=deuxd.spect[idx1].data[i,j,0].z;
            if (xaux>=xmin_e) and (xaux<=xmax_e) and (yaux>=ymin_e) and (yaux<=ymax_e) then
            begin
            deuxd.spect[idx2].data[round((xaux-xmin_e)/xstep1),round((yaux-ymin_e)/ystep1),0].X:=xaux;
            deuxd.spect[idx2].data[round((xaux-xmin_e)/xstep1),round((yaux-ymin_e)/ystep1),0].Y:=yaux;
            deuxd.spect[idx2].data[round((xaux-xmin_e)/xstep1),round((yaux-ymin_e)/ystep1),0].Z:=zaux;
            end;
          end;
end;

    { creation des echelles en X pour les graph 2D }
    { INPUT : pars[1] le nom d'un spectre 2D               }
    {         pars[2] la première valeur                   }
    {         pars[3] le pas                               }
    {         pars[4] le nouveau type des data             }
    { OUTPUT : les champs .x des data sont mis a jour      }
    function SetX1D(par:parametresNum;pars:parametresStr):integer;
    var i,ind:integer;
    begin
       ind:=und.indexof(pars[1]);
       if ind<>-1
       then begin
            for i:=0 to und.spect[ind].X-1 do  und.spect[ind].data[i,0,0].x:=par[2]+i*par[3];
            und.spect[ind].typeX:=pars[4];
            end;
    end;

    { creation des echelles en X pour les graph 2D }
    { INPUT : pars[1] le nom d'un spectre 2D               }
    {         pars[2] la première valeur                   }
    {         pars[3] le pas                               }
    {         pars[4] le nouveau type des data             }
    { OUTPUT : les champs .x des data sont mis a jour      }
    function SetX2D(par:parametresNum;pars:parametresStr):integer;
    var i,j,ind:integer;
    begin
       ind:=deuxd.indexof(pars[1]);
       for j:=0 to deuxd.spect[ind].Y-1 do
          for i:=0 to deuxd.spect[ind].X-1 do
             deuxd.spect[ind].data[i,j,0].x:=par[2]+i*par[3];
       deuxd.spect[ind].typeX:=pars[4];
    end;

    { creation des echelles en X pour les graph 2D }
    { INPUT : pars[1] le nom d'un spectre 2D               }
    {         pars[2] la première valeur                   }
    {         pars[3] le pas                               }
    { OUTPUT : les champs .x des data sont mis a jour      }
    function SetY2D(par:parametresNum;pars:parametresStr):integer;
    var i,j,ind:integer;
    begin
       ind:=deuxd.indexof(pars[1]);
       for i:=0 to deuxd.spect[ind].X-1 do
          for j:=0 to deuxd.spect[ind].Y-1 do
             deuxd.spect[ind].data[i,j,0].y:=par[2]+j*par[3];
       deuxd.spect[ind].typeY:=pars[4];
    end;

    { resample the data to cretae a new X-axis             }
    { INPUT : pars[1] le nom d'un spectre 1D               }
    {         pars[2] le pas du resampling                 }
    {         pars[3] le spectre de sortie                 }
    { OUTPUT : les champs .x des data sont mis a jour      }
    function Resample(par:parametresNum;pars:parametresStr):integer;
    var i,ind,ind2,Xsize,X2size:integer;
        x,xmin,xmax,xstep:double;
    begin
       ind:=und.indexof(pars[1]);
       if ind<>-1
       then begin
            Xsize:=und.spect[ind].X;
            Xmin:=und.spect[ind].data[0,0,0].x;Xmax:=und.spect[ind].data[Xsize-1,0,0].x;Xstep:=par[2];
            X2size:=round((Xmax-Xmin)/Xstep)+1;
            ind2:=und.addSpectre(pars[3],X2size,1,1); { nouveau spectre resamplé }
            for i:=0 to X2size-1 do
               begin
               x:=Xmin+i*Xstep;
               und.spect[ind2].data[i,0,0].x:=x;
               und.spect[ind2].data[i,0,0].z:=und.spect[ind].interpolate(x);
               end;
            end;
    end;

    { resample the data to cretae a new X-axis             }
    { INPUT : pars[1] le nom d'un spectre 1D               }
    {         par[2] le pas du resampling                 }
    {         par[3] le pas du resampling                       }
    {         pars[4] le spectre de sortie                 }
    { OUTPUT : les champs .x des data sont mis a jour      }
    function Resample2D(par:parametresNum;pars:parametresStr):integer;
    var i,j,ind,ind2,Xsize,Ysize,X2size,Y2size:integer;
        x,xmin,xmax,xstep,y,ymin,ymax,ystep:double;
    begin
       ind:=deuxd.indexof(pars[1]);
       if ind<>-1
       then begin
            Xsize:=deuxd.spect[ind].X;Ysize:=deuxd.spect[ind].Y;
            Xmin:=deuxd.spect[ind].data[0,0,0].x;Xmax:=deuxd.spect[ind].data[Xsize-1,0,0].x;Xstep:=par[2];
            Ymin:=deuxd.spect[ind].data[0,0,0].y;Ymax:=deuxd.spect[ind].data[0,Ysize-1,0].y;Ystep:=par[3];
            X2size:=round((Xmax-Xmin)/Xstep)+1;
            Y2size:=round((Ymax-Ymin)/Ystep)+1;
            ind2:=deuxd.addSpectre(pars[4],X2size,Y2size,1); { nouveau spectre resamplé }
            for i:=0 to X2size-1 do
             for j:=0 to Y2size-1 do
               begin
               x:=Xmin+i*Xstep;y:=Ymin+j*Ystep;
               deuxd.spect[ind2].data[i,j,0].x:=x;
               deuxd.spect[ind2].data[i,j,0].y:=y;
               deuxd.spect[ind2].data[i,j,0].z:=deuxd.spect[ind].interpolate2D(x,y);
               end;
            end;
    end;

    { remapping des spectres des MSGC, version sans moiré                       }
    { INPUT : un spectre 2D par[1] : X = (A-B) et Y = (A+B)                     }
    {         offset X ; offset Y                                               }
    { OUTPUT : on veut        X = (A-B)/(A+B) et Y = (A+B)                      }
    { ACHTUNG, il faut introduire des offsets                                   }
    function Remap2D_MSGC(par:parametresNum;pars:parametresStr):integer;
    var i,j,ind,qind:integer;
        qx,qy,qz,qXmin,qXmax,qXpas,qYmin,qYmax,qYpas:double;
        cste,ti,tf,auxP,auxM:double;
        sizeX,sizeY:integer;
        dqx,dqy,dqxdti,dqxdtf,dqydti,dqydtf:double;           { pas en theta initial et theta final }
        iif,jjf,imjm,ipjm,imjp,ipjp:double;
        xmin,xpas,xmax,ymin,ymax,ypas:double;
        XX,YY,XX0,YY0,offsetX,offsetY:double;
    begin
       ind:=deuxd.indexof(pars[1]); { spectre 2D a traiter }
       offsetX:=par[4];offsetY:=par[5];
       { creation du nouveau spectre }
       Xmin:=-128;Xpas:=par[2];Xmax:=128;
       Ymin:=-128;Ypas:=par[3];Ymax:=128;

       SizeX:=round((xmax-xmin)/xpas)+1;SizeY:=round((ymax-xmin)/xpas)+1;
       qind:=deuxd.addspectre(pars[1]+'_RM',SizeX,SizeY,1);
       deuxd.spect[qind].typeX:='µm-1';
       deuxd.spect[qind].typeY:='nm-1';
       { remplissage du tableau des (Qx, Qz) }
       for i:=0 to SizeX-1 do
        for j:=0 to SizeY-1 do
          begin
             XX:=Xmin+i*Xpas;
             YY:=Ymin+j*Ypas;
             deuxd.spect[qind].data[i,j,0].x:=XX;
             deuxd.spect[qind].data[i,j,0].y:=YY;
             { inversion du point que l'on cherche }
             YY0:=256-(YY+OffsetY); { ok }
             XX0:=XX*YY/128+OffsetX;
             deuxd.spect[qind].data[i,j,0].z:=deuxd.spect[ind].interpolate2D(XX0,YY0);
          end;
    end;

    { remapping des spectres des MSGC                                           }
    { INPUT : un spectre 2D par[1] : X = (A-B) et Y = (A+B)                     }
    {         offset X ; offset Y                                               }
    { OUTPUT : on veut        X = (A-B)/(A+B) et Y = (A+B)                      }
    { ACHTUNG, il faut introduire des offsets                                   }
    function Remap2D_MSGC2(par:parametresNum;pars:parametresStr):integer;
    var i,j,ind,qind:integer;
        qx,qy,qz,qXmin,qXmax,qXpas,qYmin,qYmax,qYpas:double;
        cste,ti,tf,auxP,auxM:double;
        ii,jj,iimax,jjmax,iit,jjt:integer;
        dqx,dqy,dqxdti,dqxdtf,dqydti,dqydtf:double;           { pas en theta initial et theta final }
        binning:array of array of double;
        iif,jjf,imjm,ipjm,imjp,ipjp:double;
        XX,YY,offsetX,offsetY:double;
    begin
       ind:=deuxd.indexof(pars[1]); { spectre 2D a traiter }
       offsetX:=par[2];offsetY:=par[3];
{       dX:=abs(deuxd.spect[ind].data[1,0,0].x-deuxd.spect[ind].data[0,0,0].x); { pas en X et Y }
{       dY:=abs(deuxd.spect[ind].data[0,1,0].y-deuxd.spect[ind].data[0,0,0].y); }
       { creation du nouveau spectre }
{       qXmin:=par[3];qXpas:=par[4];qXmax:=par[5];
       qYmin:=par[6];qYpas:=par[7];qYmax:=par[8]; }
       qXmin:=-128;qXpas:=1;qXmax:=128;
       qYmin:=-128;qYpas:=1;qYmax:=128;
       iimax:=round((qxmax-qxmin)/qxpas);jjmax:=round((qymax-qymin)/qypas);
       setlength(binning,iimax,jjmax);
       for i:=0 to iimax-1 do for j:=0 to jjmax-1 do binning[i,j]:=0;

       qind:=deuxd.addspectre(pars[1]+'_RM',iimax,jjmax,1);
{       deuxd.spect[qind].typeX:='1/[L]';
       deuxd.spect[qind].typeY:='1/[L]'; }
       { en attendant que les projections acceptent les types autres que 'raw' }
       deuxd.spect[qind].typeX:='raw';
       deuxd.spect[qind].typeY:='raw';

       { initialisation des champs .X et .y pour le spectre en qx qz }
       for i:=0 to deuxd.spect[qind].X-1 do
          for j:=0 to deuxd.spect[qind].Y-1 do
          begin
             deuxd.spect[qind].data[i,j,0].x:=qxmin+i*qxpas;
             deuxd.spect[qind].data[i,j,0].y:=qymin+j*qypas;
          end;
       { on scanne les points du spectre en t in  et t out }
       for i:=0 to deuxd.spect[ind].X-1 do
          for j:=0 to deuxd.spect[ind].Y-1 do
          begin
               XX:=deuxd.spect[ind].data[i,j,0].x-offsetX;
               YY:=deuxd.spect[ind].data[i,j,0].y-offsetY;
               qx:=XX/YY*128;qy:=YY; { remmapping proprement dit }
               { dans quelle cellule doit-on mettre ces points }
               { il faut verifier si ca rentre dans le graph 2D }
               iif:=((qx-qxmin)/qxpas);jjf:=((qy-qymin)/qypas);           { la position "précise" }
               ii:=round((qx-qxmin)/qxpas);jj:=round((qy-qymin)/qypas);
               iit:=floor(iif);jjt:=floor(jjf); { pour faire une "interpolation" entre 4 points en Q }
{               if (ii>=0) and (ii<iimax) and (jj>=0) and (jj<jjmax) }
               if (iit>=0) and (iit<iimax-1) and (jjt>=0) and (jjt<jjmax-1)
               then begin
                    { calcul des fractions à mettre dans chaque "boite" }
                    imjm:=(iif-iit)*(jjf-jjt); { avec im = iit }
                    ipjm:=(iit+1-iif)*(jjf-jjt);
                    imjp:=(iif-iit)*(jjt+1-jjf);
                    ipjp:=(iit+1-iif)*(jjt+1-jjf);
                    graph2Dform.sommeTotal.value:=imjm+ipjm+imjp+ipjp;
                    { version normalisée, mais ca pose des problèmes pour le signe des dqxdti }
                    { deuxd.spect[qind].data[ii,jj,0].z:=deuxd.spect[qind].data[ii,jj,0].z+deuxd.spect[ind].data[i,j,0].z/abs(dqx*dqy); }
                    deuxd.spect[qind].data[iit,jjt,0].z:=deuxd.spect[qind].data[iit,jjt,0].z+imjm*deuxd.spect[ind].data[i,j,0].z;binning[iit,jjt]:=binning[iit,jjt]+imjm; { on incrémente la boite de binning }
                    deuxd.spect[qind].data[iit+1,jjt,0].z:=deuxd.spect[qind].data[iit+1,jjt,0].z+ipjm*deuxd.spect[ind].data[i,j,0].z;binning[iit+1,jjt]:=binning[iit+1,jjt]+ipjm; { on incrémente la boite de binning }
                    deuxd.spect[qind].data[iit,jjt+1,0].z:=deuxd.spect[qind].data[iit,jjt+1,0].z+imjp*deuxd.spect[ind].data[i,j,0].z;binning[iit,jjt+1]:=binning[iit,jjt+1]+imjp; { on incrémente la boite de binning }
                    deuxd.spect[qind].data[iit+1,jjt+1,0].z:=deuxd.spect[qind].data[iit+1,jjt+1,0].z+ipjp*deuxd.spect[ind].data[i,j,0].z;binning[iit+1,jjt+1]:=binning[iit+1,jjt+1]+ipjp; { on incrémente la boite de binning }
                    end;
          end;
     { renormalisation des data par le nombre de binning }
{     for i:=0 to iimax-1 do
       for j:=0 to jjmax-1 do
         begin
           if binning[i,j]<>0 then deuxd.spect[qind].data[i,j,0].z:=deuxd.spect[qind].data[i,j,0].z/binning[i,j];
         end;     }

    end;



    { remappage d'un spectre 2D des coordonnées (theta in;theta out) verx (Qz,Qx) }
    { on suppose Tin en X et Tout en Y    en DEGRES !!!                           }
    { les unités de q sont les unités de 1/lambda                                 }
    { INPUT : pars[1], spectre 2D a remapper                                      }
    {         par[2] lambda                                                       }
    {         par[3], qxmin; par[4], qxpas; par[5], qxmax;  (en nm-1)          }
    {         par[6], qxmin; par[7], qxpas; par[8], qxmax;                     }
    {         pars[9], le nom du nouveau spectre avec les data qx,qy              }
    { OUTPUT : on crée un nouveau spectre 2D avec les coordonnées qx,qy           }
    { REM : il faut que les .x et .y soit bien initialisés                        }
    { IL MANQUE LA NORMALISATION POUR LE MOMENT }
    { IL SEMBLE QU'ON COMPTE PLUS DE COUPS QUE DANS LE SPECTRE DE DEPART !!! }
    function Remap2DtoQxQz(par:parametresNum;pars:parametresStr):integer;
    var i,j,ind,qind:integer;
        qx,qy,qz,qXmin,qXmax,qXpas,qYmin,qYmax,qYpas:double;
        cste,ti,tf,auxP,auxM:double;
        ii,jj,iimax,jjmax,iit,jjt:integer;
        dti,dtf,dqx,dqy,dqxdti,dqxdtf,dqydti,dqydtf:double;           { pas en theta initial et theta final }
        binning:array of array of double;
        iif,jjf,imjm,ipjm,imjp,ipjp:double;
    begin
       cste:=4*pi/par[2];
       ind:=deuxd.indexof(pars[1]); { spectre 2D a traiter }
       dti:=abs(deuxd.spect[ind].data[1,0,0].x-deuxd.spect[ind].data[0,0,0].x);
       dtf:=abs(deuxd.spect[ind].data[0,1,0].y-deuxd.spect[ind].data[0,0,0].y);
       { creation du nouveau spectre }
       qXmin:=par[3];qXpas:=par[4];qXmax:=par[5];
       qYmin:=par[6];qYpas:=par[7];qYmax:=par[8];
       iimax:=round((qxmax-qxmin)/qxpas);jjmax:=round((qymax-qymin)/qypas);
       setlength(binning,iimax,jjmax);
       for i:=0 to iimax-1 do for j:=0 to jjmax-1 do binning[i,j]:=0;

       qind:=deuxd.addspectre(pars[9],iimax,jjmax,1);
{       deuxd.spect[qind].typeX:='1/[L]';
       deuxd.spect[qind].typeY:='1/[L]'; }
       { en attendant que les projections acceptent les types autres que 'raw' }
       deuxd.spect[qind].typeX:='raw';
       deuxd.spect[qind].typeY:='raw';

       { initialisation des champs .X et .y pour le spectre en qx qz }
       for i:=0 to deuxd.spect[qind].X-1 do
          for j:=0 to deuxd.spect[qind].Y-1 do
          begin
             deuxd.spect[qind].data[i,j,0].x:=qxmin+i*qxpas;
             deuxd.spect[qind].data[i,j,0].y:=qymin+j*qypas;
          end;
       { on scan les points du spectre en t in  et t out }
       for i:=0 to deuxd.spect[ind].X-1 do
          for j:=0 to deuxd.spect[ind].Y-1 do
          begin
               ti:=deuxd.spect[ind].data[i,j,0].x*pi/180;
               tf:=deuxd.spect[ind].data[i,j,0].y*pi/180;
               auxP:=(ti+tf)/2;auxM:=(ti-tf)/2;
               { ces formules ne s'appliquent que pour les faisceaux reflechis !!! }
               { il y a des corrections a faire pour les faisceaux transmis   }
               qx:=cste*sin(auxP)*cos(auxM); { ACHTUNG, ca correspond a qz pour notations F.O. }
               qy:=cste*sin(auxP)*sin(auxM); { ACHTUNG ca correspond à qx pour notations F.O. }
{               dqxdti:=0.5*cste*(cos(auxP)*cos(auxM)-sin(auxP)*sin(auxM));
               dqxdtf:=0.5*cste*(cos(auxP)*cos(auxM)+sin(auxP)*sin(auxM));
               dqydti:=0.5*cste*(cos(auxP)*sin(auxM)+sin(auxP)*cos(auxM));
               dqydtf:=0.5*cste*(cos(auxP)*sin(auxM)-sin(auxP)*cos(auxM));
               dqx:=dqxdti*dti+dqxdtf*dtf;dqy:=dqydti*dti+dqydtf*dtf;     }
               { dans quelle cellule doit-on mettre ces points }
               { il faut verifier si ca rentre dans le graph 2D }
               iif:=((qx-qxmin)/qxpas);jjf:=((qy-qymin)/qypas);           { la position "précise" }
               ii:=round((qx-qxmin)/qxpas);jj:=round((qy-qymin)/qypas);
               iit:=floor(iif);jjt:=floor(jjf); { pour faire une "interpolation" entre 4 points en Q }
{               if (ii>=0) and (ii<iimax) and (jj>=0) and (jj<jjmax) }
               if (iit>=0) and (iit<iimax-1) and (jjt>=0) and (jjt<jjmax-1)
               then begin
                    { calcul des fractions à mettre dans chaque "boite" }
                    imjm:=(iif-iit)*(jjf-jjt); { avec im = iit }
                    ipjm:=(iit+1-iif)*(jjf-jjt);
                    imjp:=(iif-iit)*(jjt+1-jjf);
                    ipjp:=(iit+1-iif)*(jjt+1-jjf);
                    graph2Dform.sommeTotal.value:=imjm+ipjm+imjp+ipjp;
                    { version normalisée, mais ca pose des problèmes pour le signe des dqxdti }
                    { deuxd.spect[qind].data[ii,jj,0].z:=deuxd.spect[qind].data[ii,jj,0].z+deuxd.spect[ind].data[i,j,0].z/abs(dqx*dqy); }
                    deuxd.spect[qind].data[iit,jjt,0].z:=deuxd.spect[qind].data[iit,jjt,0].z+imjm*deuxd.spect[ind].data[i,j,0].z;binning[iit,jjt]:=binning[iit,jjt]+imjm; { on incrémente la boite de binning }
                    deuxd.spect[qind].data[iit+1,jjt,0].z:=deuxd.spect[qind].data[iit+1,jjt,0].z+ipjm*deuxd.spect[ind].data[i,j,0].z;binning[iit+1,jjt]:=binning[iit+1,jjt]+ipjm; { on incrémente la boite de binning }
                    deuxd.spect[qind].data[iit,jjt+1,0].z:=deuxd.spect[qind].data[iit,jjt+1,0].z+imjp*deuxd.spect[ind].data[i,j,0].z;binning[iit,jjt+1]:=binning[iit,jjt+1]+imjp; { on incrémente la boite de binning }
                    deuxd.spect[qind].data[iit+1,jjt+1,0].z:=deuxd.spect[qind].data[iit+1,jjt+1,0].z+ipjp*deuxd.spect[ind].data[i,j,0].z;binning[iit+1,jjt+1]:=binning[iit+1,jjt+1]+ipjp; { on incrémente la boite de binning }
                    end;
               { verification que la normalisation des surfaces des espaces reciproques est bonne }
          end;
     { renormalisation des data par le nombre de binning }
{     for i:=0 to iimax-1 do
       for j:=0 to jjmax-1 do
         begin
           if binning[i,j]<>0 then deuxd.spect[qind].data[i,j,0].z:=deuxd.spect[qind].data[i,j,0].z/binning[i,j];
         end;     }

    end;

    { conversion postion sur le detecteur en angle theta reflechi }
    { la pos "thetaOutChannel" correspond à thetaOut = thetaIn    }
    { un pas de channel PSD correspond à 0.017526 degrés          }
    { x channel de 1.04 mm et detecteur à une distance de 3400mm  }
    { N.B. les channels sont numérotés à l'envers % a theta out   }
    { INPUT : pars[1] => nom du fichier de data                   }
    {         par[2] => theta in en degrés                        }
    {         par[3] => position du faisceau réfléchi en pixel    }
    {         par[4],par[5],par[6] Qzmin,Qzpas,Qzmax en nm-1      }
    {         par[7],par[8],par[9] Qxmin,Qxpas,Qxmax en µm-1      }
    {         par[10] => nom du spectre de sortie                 }
    function RemapToFdataToQxQz(par:parametresNum;pars:parametresStr):integer;
    const Deg = 3.1415926535897932385/180;
          conv2T = 0.017526; { en °/graduation, facteur de conversion channel PSD vers ° }
          nbrTimeChannels = 300;
          nbrPSDchannels = 286;
    var i,j,k,ind,qind:integer;
        qx,qy,qz,qXmin,qXmax,qXpas,qZmin,qZmax,qZpas:double;
        ii,jj,iimax,jjmax:integer;
        tin,tout,l,specChannel:double; { theta in et theta out }
        auxP,auxM,scz,ssx,dtf,dl,dqx,dqz,dqxdtf,dqzdtf,dqxdl,dqzdl:double;    { variables auxiliaires }
        binning:array of array of integer;
    begin
     ind:=deuxd.indexof(pars[1]); { index du spectre D2 à traiter }
     { creation du nouveau spectre }
     qZmin:=par[4];qZpas:=par[5];qZmax:=par[6];
     qXmin:=par[7];qXpas:=par[8];qXmax:=par[9];
     iimax:=round((qzmax-qzmin)/qzpas);jjmax:=round((qxmax-qxmin)/qxpas);
     qind:=deuxd.addspectre(pars[10],iimax,jjmax,1);
     { création du tableau qui comptabilise le binning }
     setlength(binning,iimax,jjmax);
     for i:=0 to iimax-1 do for j:=0 to jjmax-1 do binning[i,j]:=0;
     { en attendant que les projections acceptent les types autres que 'raw' }
     deuxd.spect[qind].typeX:='µm-1';
     deuxd.spect[qind].typeY:='nm-1';
     { initialisation des champs .X et .y pour le spectre en qx qz }
     for i:=0 to deuxd.spect[qind].X-1 do
       for j:=0 to deuxd.spect[qind].Y-1 do
          begin
             deuxd.spect[qind].data[i,j,0].x:=qzmin+i*qzpas;
             deuxd.spect[qind].data[i,j,0].y:=qxmin+j*qxpas;
             deuxd.spect[qind].data[i,j,0].z:=0;
          end;

     tin:=par[2]*Deg; { angle d'incidence }
     specChannel:=par[3]; { specular beam position en n° de channel }
     k:=0;
     dtf:=0.0172*Deg;dl:=0.00639;
     for i:=0 to nbrPSDChannels-1 do
     begin
         tout:=tin+(specChannel-(i))*conv2T*Deg;
         auxP:=(tin+tout)/2;auxM:=(tin-tout)/2;
         scz:=4*pi*sin(auxP)*cos(auxM);
         ssx:=4*pi*sin(auxP)*sin(auxM);
         { ces formules ne s'appliquent que pour les faisceaux reflechis !!! }
         { il y a des corrections a faire pour les faisceaux transmis   }

         for j:=0 to nbrTimeChannels-1 do
         begin
            l:=(j*0.0638843 - 0.117479)*0.1; { (en nm) }
            Qx:=1000*ssx/l; { qx saved in µm-1 }
            Qz:=scz/l;      { qz saved in nm-1 }
            dqxdtf:=4*pi/l*0.5*(cos(auxP)*sin(auxM)-sin(auxP)*cos(auxM));
            dqzdtf:=4*pi/l*0.5*(cos(auxP)*cos(auxM)+sin(auxP)*sin(auxM));
            dqxdl:=ssx*(-1/l/l);
            dqzdl:=scz*(-1/l/l);
            dqx:=abs(dqxdtf*dtf)+abs(dqxdl*dl);dqz:=abs(dqzdtf*dtf)+abs(dqzdl*dl);
            { soit à déterminer dans quelle case tombent les neutrons }
            ii:=round((qz-qzmin)/qzpas);jj:=round((qx-qxmin)/qxpas);
            if (ii>=0) and (ii<iimax) and (jj>=0) and (jj<jjmax)
            {then deuxd.spect[qind].data[ii,jj,0].z:=deuxd.spect[qind].data[ii,jj,0].z+deuxd.spect[ind].data[i,j,0].z; }
            {then deuxd.spect[qind].data[ii,jj,0].z:=deuxd.spect[qind].data[ii,jj,0].z+deuxd.spect[ind].data[i,j,0].z/(abs(dqx*dqz)); }
            then begin
                 deuxd.spect[qind].data[ii,jj,0].z:=deuxd.spect[qind].data[ii,jj,0].z+deuxd.spect[ind].data[i,j,0].z;
                 binning[ii,jj]:=binning[ii,jj]+1; { on incrémente la boite de binning }
                 end;
         end;
     end;
     { renormalisation des data par le nombre de binning }
     for i:=0 to iimax-1 do
       for j:=0 to jjmax-1 do
         begin
           deuxd.spect[qind].data[i,j,0].z:=deuxd.spect[qind].data[i,j,0].z/binning[i,j];
         end;
    end;

    { conversion mesure temps de vol avec PSD (theta out - lambda)              }
    { en un spectre (Qx Vs Qz)                                                  }
    { la pos "thetaOutChannel" correspond à thetaOut = thetaIn                  }
    { N.B. les channels sont numérotés à l'envers % a theta out                 }
    { INPUT : pars[1] => nom du fichier de data (spectre2D gradué en Y = lambda (A°) et Y = degrées }
    {         par[2] => theta in en degrés                                      }
    {         par[3],par[4],par[5] Qzmin,Qzpas,Qzmax en nm-1                    }
    {         par[6],par[7],par[8] Qxmin,Qxpas,Qxmax en µm-1                    }
    {         par[10] => nom du spectre de sortie                               }
    function RemapTOFtoQxQz(par:parametresNum;pars:parametresStr):integer;
    const Deg = 3.1415926535897932385/180;
    var i,j,ind,qind,qindAH,SizeX,SizeY:integer;
        Qx,Qz,qXmin,qXmax,qXpas,qZmin,qZmax,qZpas:double;
        Tin,Tout,auxP,auxM,lambda1,lambda2:double;
    begin
     ind:=deuxd.indexof(pars[1]); { index du spectre D2 à traiter }
     { creation du nouveau spectre }
     qZmin:=par[3];qZpas:=par[4];qZmax:=par[5];
     qXmin:=par[6];qXpas:=par[7];qXmax:=par[8];
     SizeX:=round((qzmax-qzmin)/qzpas)+1;SizeY:=round((qxmax-qxmin)/qxpas)+1;
     qind:=deuxd.addspectre(pars[9],SizeX,SizeY,1);
     qindAH:=deuxd.addspectre(pars[9]+'_AH',SizeX,SizeY,1); { above horizon only }
     deuxd.spect[qind].typeX:='µm-1';
     deuxd.spect[qind].typeY:='nm-1';
     Tin:=par[2]*Deg;
     { remplissage du tableau des (Qx, Qz) }
     for i:=0 to SizeX-1 do
       for j:=0 to SizeY-1 do
          begin
             Qz:=qzmin+i*qzpas;
             Qx:=qxmin+j*qxpas;
             deuxd.spect[qind].data[i,j,0].x:=Qz;
             deuxd.spect[qind].data[i,j,0].y:=Qx;
             deuxd.spect[qindAH].data[i,j,0].x:=Qz;
             deuxd.spect[qindAH].data[i,j,0].y:=Qx;
             { inversion du point que l'on cherche }
             Tout:=Tin+2*Arctan(Qx*0.001/Qz); { facteur 1000 = compatibilité µm-1 et nm-1 }
             auxP:=(tin+tout)/2;auxM:=(tin-tout)/2;
{             lambda1:=4*pi/Qx*sin(auxp)*sin(auxM)*10000;    { on travaille avec des lambda en A° }
             lambda2:=4*pi/Qz*sin(auxp)*cos(auxM)*10;
             deuxd.spect[qind].data[i,j,0].z:=deuxd.spect[ind].interpolate2D(lambda2,Tout*180/pi);
             { au-dessus de l'horizon }
             if Tout>=0 then deuxd.spect[qindAH].data[i,j,0].z:=deuxd.spect[ind].interpolate2D(lambda2,Tout*180/pi) else deuxd.spect[qindAH].data[i,j,0].z:=0;
          end;
       { rajouter le tracé de la sphere d'EWALD }
    end;

    { conversion mesure temps de vol avec PSD (theta out - lambda)              }
    { en un spectre (Qx Vs Qz)                                                  }
    { la pos "thetaOutChannel" correspond à thetaOut = thetaIn                  }
    { N.B. les channels sont numérotés à l'envers % a theta out                 }
    { INPUT : pars[1] => nom du fichier de data (spectre2D gradué en Y = lambda (A°) et Y = degrées }
    {         par[2] => theta in en degrés                                      }
    {         par[3],par[4],par[5] pimin,pipas,pimax en nm-1                    }
    {         par[6],par[7],par[8] pfmin,pfpas,pfmax en µm-1                    }
    {         par[10] => nom du spectre de sortie                               }
    function RemapTOFtoPiPf(par:parametresNum;pars:parametresStr):integer;
    const Deg = 3.1415926535897932385/180;
    var i,j,ind,qind,qindAH,SizeX,SizeY:integer;
        pzi,pzf,pimin,pimax,pipas,pfmin,pfmax,pfpas:double;
        Tin,Tout,auxP,auxM,lambda1,lambda2:double;
    begin
     ind:=deuxd.indexof(pars[1]); { index du spectre D2 à traiter }
     { creation du nouveau spectre }
     pimin:=par[3];pipas:=par[4];pimax:=par[5];
     pfmin:=par[6];pfpas:=par[7];pfmax:=par[8];
     SizeX:=round((pimax-pimin)/pipas)+1;SizeY:=round((pfmax-pfmin)/pfpas)+1;
     qind:=deuxd.addspectre(pars[9],SizeX,SizeY,1);
     qindAH:=deuxd.addspectre(pars[9]+'_AH',SizeX,SizeY,1); { above horizon only }
     deuxd.spect[qind].typeX:='au';
     deuxd.spect[qind].typeY:='au';
     Tin:=par[2]*Deg;
     { remplissage du tableau des (Pzi, Pzf) }
     for i:=0 to SizeX-1 do
       for j:=0 to SizeY-1 do
          begin
             pzi:=pimin+i*pipas;
             pzf:=pfmin+j*pfpas;
             deuxd.spect[qind].data[i,j,0].x:=pzi;
             deuxd.spect[qind].data[i,j,0].y:=pzf;
             deuxd.spect[qindAH].data[i,j,0].x:=pzi;
             deuxd.spect[qindAH].data[i,j,0].y:=pzf;
             { inversion du point que l'on cherche }
             Tout:=ArcSin(sin(Tin)*pzf/pzi); { facteur 1000 = compatibilité µm-1 et nm-1 }
             lambda2:=2*pi/pzi*sin(Tin)*10; { on utilise des A° dans les data TdV }
             deuxd.spect[qind].data[i,j,0].z:=deuxd.spect[ind].interpolate2D(lambda2,Tout*180/pi);
             { au-dessus de l'horizon }
             if Tout>=0 then deuxd.spect[qindAH].data[i,j,0].z:=deuxd.spect[ind].interpolate2D(lambda2,Tout*180/pi) else deuxd.spect[qindAH].data[i,j,0].z:=0;
          end;
       { rajouter le tracé de la sphere d'EWALD }
    end;

    { tracé de lignes sur le graph pour voir comment elles se transforme de (L,T) à (Qz,Qx)       }
    { INPUT : pars[1] le spectre d'entrée                                       }
    {         pars[2] la coordonnée X0 de la droite                             }
    {         pars[3] la valeur sur la ligne                                    }
    {         pars[4] le spectre de sortie                                      }
    { Le spectre de sortie est de la taille du spectre d'entrée et avec les même coordonnées }
    { mais avec une ligne de 1 suivant l'équation x=X0                          }
    function lineX(par:parametresNum;pars:parametresStr):integer;
    var i,j,ind,qind,SizeX,SizeY:integer;
        x,X0,Xstep,Z0:double;
    begin
     ind:=deuxd.indexof(pars[1]); { index du spectre D2 à traiter }
     { creation du nouveau spectre }
     SizeX:=deuxd.spect[ind].X;SizeY:=deuxd.spect[ind].Y;
     Xstep:=deuxd.spect[ind].data[1,0,0].x-deuxd.spect[ind].data[0,0,0].x;
     qind:=deuxd.addspectre(pars[4],SizeX,SizeY,1);
     X0:=par[2];Z0:=par[3];
     { remplissage du tableau des (Qx, Qz) }
     for i:=0 to SizeX-1 do
       for j:=0 to SizeY-1 do
          begin
             x:=deuxd.spect[ind].data[i,j,0].x;
             deuxd.spect[qind].data[i,j,0].x:=x;
             deuxd.spect[qind].data[i,j,0].y:=deuxd.spect[ind].data[i,j,0].y;
             if abs(x-X0)<(Xstep/2) then deuxd.spect[qind].data[i,j,0].z:=Z0;
          end;
    end;

    { tracé de lignes sur le graph pour voir comment elles se transforme de (L,T) à (Qz,Qx)       }
    { INPUT : pars[1] le spectre d'entrée                                       }
    {         pars[2] la coordonnée X0 de la droite                             }
    {         pars[3] la valeur sur la ligne                                    }
    {         pars[4] le spectre de sortie                                      }
    { Le spectre de sortie est de la taille du spectre d'entrée et avec les même coordonnées }
    { mais avec une ligne de 1 suivant l'équation x=X0                          }
    function lineY(par:parametresNum;pars:parametresStr):integer;
    var i,j,ind,qind,SizeX,SizeY:integer;
        y,Y0,Ystep,Z0:double;
    begin
     ind:=deuxd.indexof(pars[1]); { index du spectre D2 à traiter }
     { creation du nouveau spectre }
     SizeX:=deuxd.spect[ind].X;SizeY:=deuxd.spect[ind].Y;
     Ystep:=deuxd.spect[ind].data[0,1,0].y-deuxd.spect[ind].data[0,0,0].y;
     qind:=deuxd.addspectre(pars[4],SizeX,SizeY,1);
     Y0:=par[2];Z0:=par[3];
     { remplissage du tableau des (Qx, Qz) }
     for i:=0 to SizeX-1 do
       for j:=0 to SizeY-1 do
          begin
             y:=deuxd.spect[ind].data[i,j,0].y;
             deuxd.spect[qind].data[i,j,0].x:=deuxd.spect[ind].data[i,j,0].x;
             deuxd.spect[qind].data[i,j,0].y:=y;
             if abs(y-Y0)<(Ystep/2) then deuxd.spect[qind].data[i,j,0].z:=Z0;
          end;
    end;

{ ****** procédures agissant sur les spectres 3D }
    function DelSpectre3D(par:parametresNum;pars:parametresStr):integer;
    begin
         troisd.delete(pars[1]);
    end;
    function AddSpectre3D(par:parametresNum;pars:parametresStr):integer;
    begin
         troisd.addition(pars[1],pars[2],pars[3]);
    end;
{Somme Total sur le spectre
    pars[1] Nom3D
    par[2] nom variable parseur
    le résultat est stoké dans la boite noire
    ou dans la variable du parseur pars[6]si <>'' ex "var"}
    function IntegraleSpectre3D(par:parametresNum;pars:parametresStr):integer;
    var vind,i,j,k:integer;
        temp:double;
    begin
    vind:=troisd.indexof(pars[1]);
    if vind>0 then
       begin
       temp:=0;
       for i:=0 to troisd.spect[vind].X-1  do
          for j:=0 to troisd.spect[vind].Y-1  do
              for k:=0 to troisd.spect[vind].LT-1  do
              temp:=temp+troisd.spect[vind].data[i,j,k].Z;

       if pars[2]<>'' then interpreteurform.parser1.setvariable(pars[2],temp)
       else  boitnoir.receivetext(floattostr(temp));
       end;

    end;
    function ReadMoni3D(par:parametresNum;pars:parametresStr):integer;
    var vind:integer;
        temp:double;

    begin
    vind:=troisd.indexof(pars[1]);
    if vind>0 then
       begin
       temp:=troisd.spect[vind].moniteur;
       if pars[2]<>'' then interpreteurform.parser1.setvariable(pars[2],temp)
       else  boitnoir.receivetext(floattostr(temp));
       end;
    end;
  {procedure permettant de separer un spectre troisd en spectre 2d (selon la dim LT)}
  {INPUT pars[1] : nom du spectre 3D
         pars[2] : nom du spectres 2D
         par[3]  : numero de frame 1<..<LT
         pars[4] : mode de calcul du moniteur
                   norm/nombre : divise le moniteur par le nombre de frame
                   norm/inter : multiplie le moniteur par l'intervale lt[i]-lt[i-1]/Temps Total
                   rien copie directement le moniteur}
  function Spectre3DTo2D(par:parametresNum;pars:parametresStr):integer;
  var vind3D,vind2D,i,j,l:integer;
      X,Y,LT:integer;
      delta:double;
  begin
  vind3d:=troisd.indexof(pars[1]);
  if vind3d>0 then
  begin
  X:=troisd.spect[vind3D].X;
  Y:=troisd.spect[vind3D].Y;
  LT:=troisd.spect[vind3D].LT;
  l:=round(Par[3])-1;
  if (l>=0) and (l<=LT-1) then
  begin
    {création du spectre 2D recepteur}
    vind2D:=deuxd.addspectre(pars[2],X,Y,1);
    {chargement des data et echelle X,Y}
    for i:=0 to X-1 do
       for j:=0 to Y-1 do
          begin
          deuxd.spect[vind2D].data[i,j,0].x:=troisd.spect[vind3D].data[i,j,l].x;
          deuxd.spect[vind2D].data[i,j,0].y:=troisd.spect[vind3D].data[i,j,l].y;
          deuxd.spect[vind2D].data[i,j,0].z:=troisd.spect[vind3D].data[i,j,l].z;
          deuxd.spect[vind2D].data[i,j,0].lt:=troisd.spect[vind3D].data[i,j,l].lt;
          end;
    {chargement des infos}
    deuxd.spect[vind2D].comment:=troisd.spect[vind3D].comment;
    deuxd.spect[vind2D].typeX:=troisd.spect[vind3D].typeX;
    deuxd.spect[vind2D].typeY:=troisd.spect[vind3D].typeY;
    deuxd.spect[vind2D].typeLT:=troisd.spect[vind3D].typeLT;
    {chargement des conditions expérimentales}
    for i:=0 to troisd.spect[vind3D].ExpCondNbr-1 do
       deuxd.spect[vind2D].SetExpCond(troisd.spect[vind3D].experimentalConditions[i].name,troisd.spect[vind3D].experimentalConditions[i].value);

    deuxd.spect[vind2D].SetExpCond('lt',troisd.spect[vind3D].data[0,0,l].lt);

    {chargement du moniteur: 3 options en fonction de pars[3]}
    if pars[4]='norm/nombre' then
        begin {normalisation par le nombre de slice}
        deuxd.spect[vind2D].moniteur:=troisd.spect[vind3D].moniteur/LT;
        deuxd.spect[vind2D].SetExpCond('NormMoniteur',1);
        end
    else
        if  pars[4]='norm/inter' then
            begin  {normalisation par la durée de la frame}
            if l=0 then delta:=troisd.spect[vind3D].data[0,0,l].lt
               else  delta:=troisd.spect[vind3D].data[0,0,l].lt-troisd.spect[vind3D].data[0,0,l-1].lt;
            deuxd.spect[vind2D].moniteur:=troisd.spect[vind3D].moniteur*delta/troisd.spect[vind3D].data[0,0,troisd.spect[vind3D].LT-1].lt;
            deuxd.spect[vind2D].SetExpCond('NormMoniteur',2);
            end
        else
            begin {pas de normalisation}
            deuxd.spect[vind2D].moniteur:=troisd.spect[vind3D].moniteur;
            deuxd.spect[vind2D].SetExpCond('NormMoniteur',0);
            end;
    end;
  end;
  end;

{ calcul de la transformée de FOurier }
{ INPUT : pars[1] nom du spectre (pour le moment 1D par defaut }
{         par[2] le premier point, par[3], la longueur du sub-vecteur a transformer }
{ OUTPUT : les spectres transformés sont sorties en MySpectre_FFT }
  function FFT(par:parametresNum;pars:parametresStr):integer;
  begin
      und.FFT(pars[1],round(par[2]),round(par[3]),pars[1]+'_FFT');
  end;

{ calcul de la transformée de FOurier }
{ INPUT : pars[1] nom du spectre (pour le moment 1D par defaut }
{         par[2] le premier point, par[3], la longueur du sub-vecteur a transformer }
{ OUTPUT : les spectres transformés sont sorties en MySpectre_FFT }
  function FFT2(par:parametresNum;pars:parametresStr):integer;
  begin
      deuxd.FFT2(pars[1],round(par[2]),round(par[3]),round(par[4]),round(par[5]),pars[1]+'_FFT');
  end;

{ calcul du moduel d'un vecteur }
  function Module1D(par:parametresNum;pars:parametresStr):integer;
  begin
      und.Module1D(pars[1],pars[2]);
  end;

{ calcul du moduel d'un vecteur }
  function Module2D(par:parametresNum;pars:parametresStr):integer;
  begin
      deuxd.Module2D(pars[1],pars[2]);
  end;

{ flip des data haut-bas }
  function FlipUD(par:parametresNum;pars:parametresStr):integer; { flipping des data UP - DOWN }
  var ind:integer;
  begin
     deuxd.spect[deuxd.indexof(pars[1])].flipUD;
  end;

{ flip des data haut-bas }
  function FlipLR(par:parametresNum;pars:parametresStr):integer; { flipping des data UP - DOWN }
  var ind:integer;
  begin
     deuxd.spect[deuxd.indexof(pars[1])].flipLR;
  end;

{ passage d'un axe des abscisses gradué en lambda à un axe gradué en Q          }
{ INPUT : par[1] nom du fichier à regraduer                                     }
{         par[2] theta in                                                       }
  function ConvertL2Q(par:parametresNum;pars:parametresStr):integer;
  var i,ind,ind2,sizeX:integer;
      theta:double;
  begin
     ind:=und.indexof(pars[1]);
     sizeX:=und.spect[ind].X;
     ind2:=und.addspectre(pars[3],sizeX,1,1);
     theta:=par[2];
     if ind<>-1
     then begin
          for i:=0 to sizeX-1 do
          begin
             und.spect[ind2].data[sizeX-1-i,0,0].x:=4*pi/und.spect[ind].data[i,0,0].x*sin(theta*pi/180);
             und.spect[ind2].data[sizeX-1-i,0,0].z:=und.spect[ind].data[i,0,0].z;
          end;
          end;
  end;

  { INPUT : pars[1] , le nom du fichier 1D de data à appender                   }
  {         pars[2] , le nom "physique" du fichier de data à appender           }
  {         pars[3] , l'angle d'incidence auquel cela correpsond                }
  {         pars[4] , la cellule ou se trouve la reflexion spéculaire           }
  {         pars[5] , le pas angulaire en delta theta par cellule sur le compteur }
  function appendPSDdata(par:parametresNum;pars:parametresStr):integer;
  var i,ind,sizeX:integer;
      F:textFile;
      thetain,thetaout,cellX,step,intensity:double;
      filename,s:string;
  begin
     ind:=und.indexof(pars[1]);

     if ind<>-1
     then begin
          sizeX:=und.spect[ind].X;
          filename:=pars[2];
          thetain:=par[3];
          cellX:=par[4];
          step:=par[5];
          AssignFile(F, FileName);
          {$I-} Reset(F); {$I+}
          If IOResult = 0 then append(F) else rewrite(f);
          for i:=0 to sizeX-1 do
          begin
             thetaout:=(cellX-i)*step+thetaIn; { angle de réflexion }
             intensity:=und.spect[ind].data[i,0,0].z;
             s:=floatToStr(thetaIn)+#9+floatToStr(thetaOut)+#9+floatToStr(intensity)+#9+floatToStr(sqrt(Intensity));
             writeln(F,s);
          end;
          CloseFile(F);
          end;
  end;

  { INPUT : pars[1] , le nom du fichier 2D à thresholder                        }
  {         pars[2] , le threshold                                              }
  {         pars[3] , le nom du spectre de sortie                               }
  function threshold(par:parametresNum;pars:parametresStr):integer;
  var i,j,ind,ind2,Xsize,Ysize:integer;
      seuil,aux:double;
  begin
     ind:=deuxd.indexof(pars[1]);
     seuil:=par[2];
     Xsize:=deuxd.spect[ind].X;
     Ysize:=deuxd.spect[ind].Y;
     ind2:=deuxd.addspectre(pars[3],Xsize,Ysize,1);

     for j:=0 to Ysize-1 do
       for i:=0 to Xsize-1 do
       begin
          aux:=deuxd.spect[ind].data[i,j,0].z;
          if aux>=seuil
          then deuxd.spect[ind2].data[i,j,0].z:=1
          else deuxd.spect[ind2].data[i,j,0].z:=0;
       end;
   end;

  { INPUT : pars[1] , le nom du fichier 2D à traiter                            }
  {         pars[2] , le nom du spectre de sortie                               }
  function FindCentres(par:parametresNum;pars:parametresStr):integer;
  var i,j,idx,p,indA,indAux,indB,indM,Xsize,Ysize,idxP,q,Bx1,bX2,bY1,bY2:integer;
      seuil,aux:double;
      barX:array[1..32768] of word;
      barY:array[1..32768] of word;

  begin
     indA:=deuxd.indexof(pars[1]);
     Xsize:=deuxd.spect[indA].X;
     Ysize:=deuxd.spect[indA].Y;
     indM:=deuxd.addspectre(pars[2],Xsize,Ysize,1);
     indAux:=deuxd.addspectre('aux',Xsize,Ysize,1);
     indB:=deuxd.addspectre('auxB',Xsize,Ysize,1);

     { B = A }
     for j:=1 to Ysize-2 do
       for i:=1 to Xsize-2 do
          deuxd.spect[indB].data[i,j,0].z:=deuxd.spect[indA].data[i,j,0].z;

     { reduire } { suppression des pixels parasites }
     for j:=1 to Ysize-2 do
       for i:=1 to Xsize-2 do
          if (deuxd.spect[indA].data[i,j,0].z=1) and
             (  (deuxd.spect[indA].data[i-1,j-1,0].z=0) or (deuxd.spect[indA].data[i-1,j,0].z=0)
             or (deuxd.spect[indA].data[i-1,j+1,0].z=0) or (deuxd.spect[indA].data[i,j-1,0].z=0)
             or (deuxd.spect[indA].data[i,j+1,0].z=0)   or (deuxd.spect[indA].data[i+1,j-1,0].z=0)
             or (deuxd.spect[indA].data[i+1,j,0].z=0)   or (deuxd.spect[indA].data[i+1,j+1,0].z=0) )
          then deuxd.spect[indB].data[i,j,0].z:=0;

     { recherche centres }
     { Aux = B }
     for j:=1 to Ysize-2 do
       for i:=1 to Xsize-2 do
          deuxd.spect[indAux].data[i,j,0].z:=deuxd.spect[indB].data[i,j,0].z;

     for p:=1 to 4 do { 4 passages suffisent en general }
     begin
       for j:=1 to Ysize-2 do
         for i:=1 to Xsize-2 do
             if (deuxd.spect[indB].data[i,j,0].z=1) and
             (  (deuxd.spect[indB].data[i-1,j-1,0].z=0) and (deuxd.spect[indB].data[i-1,j,0].z=0)
             and (deuxd.spect[indB].data[i-1,j+1,0].z=0) and (deuxd.spect[indB].data[i,j-1,0].z=0)
             and (deuxd.spect[indB].data[i,j+1,0].z=0)   and (deuxd.spect[indB].data[i+1,j-1,0].z=0)
             and (deuxd.spect[indB].data[i+1,j,0].z=0)   and (deuxd.spect[indB].data[i+1,j+1,0].z=0) )
          then deuxd.spect[indM].data[i,j,0].z:=1
          else if (deuxd.spect[indAux].data[i,j,0].z=1) and
               (  (deuxd.spect[indAux].data[i-1,j-1,0].z=0) or (deuxd.spect[indAux].data[i-1,j,0].z=0)
               or (deuxd.spect[indAux].data[i-1,j+1,0].z=0) or (deuxd.spect[indAux].data[i,j-1,0].z=0)
               or (deuxd.spect[indAux].data[i,j+1,0].z=0)   or (deuxd.spect[indAux].data[i+1,j-1,0].z=0)
               or (deuxd.spect[indAux].data[i+1,j,0].z=0)   or (deuxd.spect[indAux].data[i+1,j+1,0].z=0) )
              then deuxd.spect[indB].data[i,j,0].z:=0
              else deuxd.spect[indB].data[i,j,0].z:=deuxd.spect[indAux].data[i,j,0].z;
       for j:=1 to Ysize-2 do
         for i:=1 to Xsize-2 do
          deuxd.spect[indAux].data[i,j,0].z:=deuxd.spect[indB].data[i,j,0].z;
     end;

    { recherche barycentres }
    for idx:=1 to 4 do { 4 passages suffisent en general }
    begin
    idxP:=1;
    { creation de la liste des points residuels }
    for j:=1 to Ysize-2 do
      for i:=1 to Xsize-2 do
        if deuxd.spect[indM].data[i,j,0].z=1 then begin barX[idxp]:=i;barY[idxp]:=j;inc(idxp) end;
    dec(idxP);

    for p:=1 to idxP do
      for q:=1 to idxP do
      begin
        bX1:=barX[p];bY1:=barY[p];bX2:=barX[q];bY2:=barY[q];
        if ((sqr(bX1-bX2)+sqr(bY1-bY2))<50) and (p<>q)
        then begin deuxd.spect[indM].data[bX1,bY1,0].z:=0;
                   deuxd.spect[indM].data[bX2,bY2,0].z:=0;
                   deuxd.spect[indM].data[round((bX1+bX2)/2),round((bY1+bY2)/2),0].z:=1; end;
      end;
    end;

    deuxd.deletespectre(indAux);
    deuxd.deletespectre(indB);
    end;

  { INPUT : pars[1] , le nom du fichier 2D à traiter                            }
  {         pars[2] , le nom du spectre de sortie                               }
  function FindCentres2(par:parametresNum;pars:parametresStr):integer;
  const sx=5;
        sy=10;
  var i,j,p,q,ind,indM,indB,Xsize,Ysize,idxT,idxP,l:integer;
{      ListeTx:array[1..32768] of TIntList; { liste des trous de la matrice } { toutes les coordonnées X pour un trou }
{      ListeTy:array[1..32768] of TintList; }
      ListeTx:array[1..3000,0..121] of word; { liste des trous de la matrice } { toutes les coordonnées X pour un trou }
      ListeTy:array[1..3000,0..121] of word;

      M:array of array of word; { tableau des pixels }
      x,y:double;

  begin
     ind:=deuxd.indexof(pars[1]); { la matrice de départ }
     Xsize:=deuxd.spect[ind].X;
     Ysize:=deuxd.spect[ind].Y;
     indM:=deuxd.addspectre(pars[2],Xsize,Ysize,1);

     indB:=deuxd.addspectre('auxB',Xsize,Ysize,1);
     { B = A }
     for j:=1 to Ysize-2 do
       for i:=1 to Xsize-2 do
          deuxd.spect[indB].data[i,j,0].z:=deuxd.spect[ind].data[i,j,0].z;

     { reduire } { suppression des pixels parasites }
     for j:=1 to Ysize-2 do
       for i:=1 to Xsize-2 do
          if (deuxd.spect[ind].data[i,j,0].z=1) and
             (  (deuxd.spect[ind].data[i-1,j-1,0].z=0) or (deuxd.spect[ind].data[i-1,j,0].z=0)
             or (deuxd.spect[ind].data[i-1,j+1,0].z=0) or (deuxd.spect[ind].data[i,j-1,0].z=0)
             or (deuxd.spect[ind].data[i,j+1,0].z=0)   or (deuxd.spect[ind].data[i+1,j-1,0].z=0)
             or (deuxd.spect[ind].data[i+1,j,0].z=0)   or (deuxd.spect[ind].data[i+1,j+1,0].z=0) )
          then deuxd.spect[indB].data[i,j,0].z:=0;

     { on fait une copie de la matrice de départ dans un tableau plus compact }
     SetLength(M,Xsize,Ysize);
     for j:=0 to Ysize-1 do
       for i:=0 to Xsize-1 do
          M[i,j]:=round(deuxd.spect[indB].data[i,j,0].z); { valeurs 0 ou 1      }

     idxT:=0; { index du trou }
     for j:=0 to Ysize-1-sy do
       for i:=0+sx to Xsize-1-sx do
         if M[i,j]=1
         then begin
              idxP:=0;
              inc(idxT);
              { ListeTx[idxT]:=TintList.create;ListeTx[idxT].clear;ListeTx[idxT].sorted:=false; }
              for p:=i-sx to i+sx do
                for q:=j to j+sy do
                  if M[p,q]=1 then
                  begin inc(idxP);ListeTx[idxT][IdxP]:=p;ListeTy[idxT][idxP]:=q;M[p,q]:=0;  end;
              ListeTx[idxT][0]:=idxP;ListeTy[idxT][0]:=idxP;
              end;

     { creation de la matrice des positions des trous }
     for p:=1 to idxT do
     begin
        x:=0;y:=0;
        l:=ListeTx[p][0];
        for q:=1 to l do begin x:=x+ListeTx[p][q];y:=y+ListeTy[p][q]; end;
        x:=x/l;y:=y/l;
        { remplissage de la matrice de sortie }
        deuxd.spect[indM].data[round(x),round(y),0].z:=1;
     end


  end;

  { INPUT : pars[1] , le nom du fichier 2D à traiter                            }
  {         pars[2] , le nom du spectre de sortie                               }
  { méthode récursive                                                           }
  function FindCentres3(par:parametresNum;pars:parametresStr):integer;
  const sx=5;
        sy=10;
        diametreMaxTrou = 256;
  type  Matrix=array of array of byte;
  var i,j,p,q,ind,indM,indB,indHist,Xsize,Ysize,idxT,idxP,l,indT,indTft,indTftM,IndTftTot,indH:integer;
      offset,xb,yb,xp,yp:integer;
{      ListeTx:array[1..32768] of TIntList; { liste des trous de la matrice } { toutes les coordonnées X pour un trou }
{      ListeTy:array[1..32768] of TintList; }
{      ListeTx:array[1..1500,0..TailleMaxTrou] of word; { liste des trous de la matrice } { toutes les coordonnées X pour un trou }
{      ListeTy:array[1..1500,0..TailleMaxTrou] of word; }
      M:Matrix; { tableau des pixels }
      x,y:double;
      Pm,PmTot,temp,Phist:TMtx; { matrice contenant la forme du trou }
      TrouSurBord:boolean;

      procedure Process(M:matrix;i,j:integer);
      begin
         M[i,j]:=0;
         inc(idxP);ListeTx[idxT][IdxP]:=i;ListeTy[idxT][idxP]:=j; { on rajoute le pixel }
         { on visite l'environnement du pixel }
         if ((i-1)>=0) and ((j-1)>=0) then if M[i-1,j-1]=1 then Process(M,i-1,j-1);
         if                ((j-1)>=0) then if M[i,j-1]=1 then Process(M,i,j-1);
         if ((i+1)<Xsize)             then if M[i+1,j]=1 then Process(M,i+1,j);
         if ((i-1)>=0)                then if M[i-1,j]=1 then Process(M,i-1,j);
         if ((i+1)<Xsize)             then if M[i+1,j]=1 then Process(M,i+1,j);
         if ((i-1)>=0) and ((j+1)<Ysize)    then if M[i-1,j+1]=1 then Process(M,i-1,j+1);
         if                ((j+1)<Ysize)    then if M[i,j+1]=1   then Process(M,i,j+1);
         if ((i+1)<Xsize) and ((j+1)<Ysize) then if M[i+1,j+1]=1 then Process(M,i+1,j+1);
      end;

  begin
     CreateIt(Pm,PmTot,temp,Phist);
     Pm.size(DiametreMaxTrou,DiametreMaxTrou,true); { matrice qui va contenir la forme du trou et sa fft }
     temp.size(DiametreMaxTrou,DiametreMaxTrou,false); { matrice qui va contenir la forme du trou et sa fft }
     PmTot.size(DiametreMaxTrou,DiametreMaxTrou,false);PmTot.setZero; { matrice qui va contenir la forme du trou et sa fft }
     Phist.size(DiametreMaxTrou,DiametreMaxTrou,true);Phist.setZero; { matrice qui va contenir l'histogramme des trous en 2D }

     ind:=deuxd.indexof(pars[1]); { la matrice de départ }
     Xsize:=deuxd.spect[ind].X;
     Ysize:=deuxd.spect[ind].Y;
     indM:=deuxd.addspectre(pars[2],Xsize,Ysize,1);
     indB:=deuxd.addspectre('auxB',Xsize,Ysize,1);
     indHist:=deuxd.addspectre('Histogramme',DiametreMaxTrou,DiametreMaxTrou,1);
     { B = A }
     for j:=0 to Ysize-1 do
       for i:=0 to Xsize-1 do
          deuxd.spect[indB].data[i,j,0].z:=deuxd.spect[ind].data[i,j,0].z;
     { reduire } { suppression des pixels parasites }
     { on désactive cette partie de nettoyage parce qu'on utilise maintenant une image traitée dans ImageTool }
     { qui est lissée et les trous ont alors une belle forme ; il n'y a plus de pixels parasites }
{     for j:=1 to Ysize-2 do
       for i:=1 to Xsize-2 do
          if (deuxd.spect[ind].data[i,j,0].z=1) and
             (  (deuxd.spect[ind].data[i-1,j-1,0].z=0) or (deuxd.spect[ind].data[i-1,j,0].z=0)
             or (deuxd.spect[ind].data[i-1,j+1,0].z=0) or (deuxd.spect[ind].data[i,j-1,0].z=0)
             or (deuxd.spect[ind].data[i,j+1,0].z=0)   or (deuxd.spect[ind].data[i+1,j-1,0].z=0)
             or (deuxd.spect[ind].data[i+1,j,0].z=0)   or (deuxd.spect[ind].data[i+1,j+1,0].z=0) )
          then deuxd.spect[indB].data[i,j,0].z:=0; }
     { on fait une copie de la matrice de départ dans un tableau plus compact }
     SetLength(M,Xsize,Ysize);
     for j:=0 to Ysize-1 do
       for i:=0 to Xsize-1 do M[i,j]:=round(deuxd.spect[indB].data[i,j,0].z); { valeurs 0 ou 1 }

     { algorithme recursif de recherche des trous }
     idxT:=0; { index du trou }
     for j:=0 to Ysize-1 do
       for i:=0 to Xsize-1 do
         if M[i,j]=1
         then begin
                inc(idxT);idxP:=0;
                process(M,i,j);
                ListeTx[idxT][0]:=idxP;ListeTy[idxT][0]:=idxP; { stockage du nombre de trous }
                { test s'il s'agit d'un trou sur le bord }
                TrouSurBord:=false;
                for q:=1 to idxP do
                begin xp:=ListeTx[idxT][q];yp:=ListeTy[idxT][q];
                      if (xp=0) or (yp=0) or (xp=(Xsize-1)) or (yp=(Ysize-1)) then TrouSurBord:=true; end;
                if TrouSurBord then dec(idxT); { on detruit le trou de la liste }
              end;

     { creation de la matrice des positions des trous }
     for p:=1 to idxT do
     begin
        x:=0;y:=0;
        l:=ListeTx[p][0];
        for q:=1 to l do begin x:=x+ListeTx[p][q];y:=y+ListeTy[p][q]; end;
        x:=x/l;y:=y/l;
        { remplissage de la matrice de sortie }
        deuxd.spect[indM].data[round(x),round(y),0].z:=1;
     end;

     { traitement statistique des trous }
     { creation de l'histogramme de repartition des trous }
     indH:=und.addSpectre(pars[1]+'_hist',TailleMaxTrou,1,1);
     for p:=1 to idxT do { parcours de la liste de trous }
     begin
        l:=ListeTx[p][0]; { taille du trou }
        und.spect[indH].data[l,0,0].z:=und.spect[indH].data[l,0,0].z+1;
     end;
     { calcul de la TF moyenne des trous }
     { on balaie la liste des trous }
     offset:=DiametreMaxTrou div 2; { pour centrer le trou dans la matrice }
     for p:=1 to idxT do
     begin
        { on scanne les pixels pour calculer le barycentre }
        xb:=0;yb:=0;l:=ListeTx[p][0]; { nombre de pixesl }
        for q:=1 to l do begin xb:=xb+ListeTx[p][q];yb:=yb+ListeTy[p][q]; end;
        xb:=round(xb/l);yb:=round(yb/l); { barycentre du trou (arrondi) }
        { remplissage de la matrice dessinant le trou }
        Pm.SetZero;
        for q:=1 to l do
        begin
           xp:=ListeTx[p][q];yp:=ListeTy[p][q];
           Pm.Cvalues[xp-xb+offset,yp-yb+offset]:=C_ONE;
        end;
        Phist.add(Pm); { matrice de l'histogramme des trous }
        Pm.fft; { calcul de la FT du trou }
        temp.abs(Pm);
        PmTot.add(temp.sqrElem);
     end;
     indT:=deuxd.addSpectre('P',DiametreMaxTrou,DiametreMaxTrou,1); { un spectre contenant la forme du trou }
     { remplissage de la matrice T }
     for i:=0 to DiametreMaxTrou-1 do
      for j:=0 to DiametreMaxTrou-1 do
      begin
        deuxd.spect[indT].data[i,j,0].z:=PmTot.values[i,j];
        deuxd.spect[indHist].data[i,j,0].z:=Real(Phist.Cvalues[i,j]);
      end;
     deuxd.spect[indT].fftshift;
  end;

{ graduation de l'axe des abscisses pour le smesures en TOF (EROS)              }
function SetTOFaxisLambda(par:parametresNum;pars:parametresStr):integer;
var i,ind:integer;
    channelWidth,Retard:double;
begin
   ChannelWidth:=par[2];
   retard:=par[3];
   ind:=und.indexof(pars[1]);
   if ind<>-1
   then begin
        for i:=0 to und.spect[ind].X-1 do  und.spect[ind].data[i,0,0].x:=5.9e-4*(i*channelWidth+retard);
        und.spect[ind].typeX:=pars[4];
        end;
end;

{ graduation de l'axe des abscisses pour le smesures en TOF (EROS)              }
function SetTOFaxisQz(par:parametresNum;pars:parametresStr):integer;
var i,ind,ind2,size:integer;
    channelWidth,Retard,angle:double;
begin
   ChannelWidth:=par[2];
   retard:=par[3];
   angle:=par[4]*Pi/180;
   ind:=und.indexof(pars[1]);Size:=und.spect[ind].X;
   ind2:=und.addspectre(pars[1]+'_Q',size,1,1);
   if ind<>-1
   then begin
        for i:=0 to size-1 do
        begin
           und.spect[ind2].data[size-1-i,0,0].x:=4*pi*sin(angle)/(5.9e-5*(i*channelWidth+retard));
           und.spect[ind2].data[size-1-i,0,0].z:=und.spect[ind].data[i,0,0].z
        end;
        und.spect[ind2].typeX:=pars[4];
        end;
end;

{ graduation de l'axe des abscisses pour le smesures en TOF (EROS)              }
function Raboutage(par:parametresNum;pars:parametresStr):integer;
var i1,i2,i3,ind1,ind2,ind3,size1,size2:integer;
    channelWidth,Retard,angle,limite,x:double;
begin
   ind1:=und.indexof(pars[1]);Size1:=und.spect[ind1].X;
   ind2:=und.indexof(pars[2]);Size2:=und.spect[ind2].X;
   ind3:=und.addspectre(pars[4],size1+size2,1,1);
   limite:=par[3];
   i1:=0;
   x:=und.spect[ind1].data[i1,0,0].x;
   while x<=limite do
   begin
     und.spect[ind3].data[i1,0,0].x:=x;
     und.spect[ind3].data[i1,0,0].z:=und.spect[ind1].data[i1,0,0].z;
     inc(i1);
     x:=und.spect[ind1].data[i1,0,0].x;
   end;
   i2:=0;
   repeat
     inc(i2);x:=und.spect[ind2].data[i2,0,0].x;
   until x>=limite;
   i3:=0;
   while i2<(size2-1) do
   begin
     und.spect[ind3].data[i1+i3,0,0].x:=x;
     und.spect[ind3].data[i1+i3,0,0].z:=und.spect[ind2].data[i2,0,0].z;
     inc(i2);x:=und.spect[ind2].data[i2,0,0].x;
     inc(i3)
   end;
   und.spect[ind3].X:=i1+i3;
end;

end.
