{$DEFINE PERMITIR_DEFORMADORES_NULOS}
unit uanalisisserialbasico;

interface

uses
  Classes,
  SysUtils,
  xmatdefs,
  matreal,
  uregresion,
  uAuxiliares,
  useriestemporales,
  umodelosintcegh,
  wrffti01,
  wrfftf01,
  uradiacionsolar,

  Types;

type
  {TanalisisSerialcmd}
    TanalisisSerialcmd = class
    cbAniosAnalogos: boolean;                           // false
    cbCopiarUltimomCicloComoEstadoinicial: boolean;     // false
    cbFiltradoKTPorIh0: boolean;                        // false
    cbFiltrarMenores: boolean;                          // true
    cbFiltroCiclico: boolean;                           // false
    cb_FiltrarAlGaussianizar: boolean;                  // false
    cbCurvaAero: boolean;                               // false
    cb_Filtrarmenores_CalcErrores: boolean;             // true
    cbTendenciaExponencial: boolean;                    // false
    cb_InfoParcial: boolean;                            // false
    cbCompletarHuecosConRuidoBlanco: boolean;           // false
    eArchiSeriesDeDatos: string;               //
    eArchiCEGH : string;
    eMinicicloCaracteristico: string;          // 24
    eMinicicloCaracteristicoTendencia: string; // 24
    eNClusters: string;                        // 3
    eGradoTendencia: string;                   // 1
    eNCronicas: string;                        // 100
    eNDecimalesDesformadores: string;          // 3
    eNDigitosDesformadores: string;            // 8
    eNPuntosPorMiniCiclo: string;              // 0
    eNP_Deformadores: string;                  // 200
    eOrdenDelFiltro: string;                   // 1
    eOrdenESHY: string;                        // 4
    eOverlapping: string;                      // 3
    eSemanaInicioVentanaAnaloga: string;       // 27
    eTraslapping: string;                      // 0
    eUmbralAlGaussianizar: string;             // 10
    eUmbralFiltro: string;                     // -1111
    eVarianzaDeLoNoExplicado: string;
    eUmral_calcerrores: string;                    // -1111
    eNRetardos: string;                        // 1
    eNNeuronasPorCanal: string;                // 5
    eNCronicasRuido: string;                   // 1
    ePrecisionMedida: string;                  // 0.03

    rgTipoModelo : integer;                   // 0
    rbg_CalculoB : integer;
    lstAniosAnalogos: string;

    private
      seriesDeDatos: TSeriesDeDatos;
      aniosanalogos: array of integer;
      semanaDeInicio: integer;
      kBuscarDesde: integer;
    public
      { Public declarations }
      cegh: TModeloCEGH;

      procedure GetAniosAnalogos;
      procedure MascararAniosNoAnalogos(datos: TSeriesDeDatos; mascara: double);
      function Mascarado(anio, semana: integer): boolean;
      function buscarAnio(anio: integer): integer;
      constructor Create(nombreArchivo:string);
      procedure Analizarcmd(Limpieza:boolean);

      procedure Limpiar;
      procedure Limpiar_covars_k_gaussianas;
      procedure Limpiar_FFTSeriesGaussianas;
      procedure Limpiar_Matriz_XXT;
      procedure Limpiar_series_gaussianas;
      procedure Limpiar_btb;

    end;




implementation

//{$R *.lfm}

// recorre las series y quita los tramos en que halla actuado el filtro
// acortando las series.
procedure AcortarTramosFiltrados(var series: TDAOfVectR; umbralFiltro: NReal);

var
  j, jval, NSems: integer;
  flg_Filtrado: boolean;
  iserie: integer;

begin
  NSems := Series[0].n;
  j := 1;
  while (j <= nSems) do
  begin
    //detecto si actuó el filtro en alguna de las series.
    flg_Filtrado := False;
    for iserie := 0 to high(series) do
      if series[iserie].e(j) <= umbralFiltro then
      begin
        flg_Filtrado := True;
        break;
      end;

    // si actuó el filtro acortamos todas las series.
    if flg_Filtrado then
    begin
      for iserie := 0 to high(series) do
      begin
        for jval := j to nSems - 1 do
          series[iserie].pon_e(jval, series[iserie].e(jval + 1));
      end;
      Dec(nSems);
    end
    else
      Inc(j);
  end;

  // si corresponde acortamos las series.
  if nSems < series[0].n then
  begin
    for iserie := 0 to high(series) do
    begin
      setlength(series[iserie].pv, nSems + 1);
      series[iserie].n := nSems;
    end;
  end;
end;



// retorna la matriz B triangular Inferior de la factorización de
// Cholesky que tal que B*transpuesta(B) es la matriz de covarianzas
// de las series.
function descuadrador_Cholesky(var series: TDAOfVectR; filtrar: boolean;
  umbralFiltro: NReal): TMatR;

var
  A: TMatR; // matriz de covarianzas
  B: TMatR;
  k, j: integer;
  m: NReal;
  NDatos: integer;
  DimRes: Integer;

begin

  // SI la orden es filtrar, acortamos las series
  // quitando los tramos en los que actuó el filtro.
  if Filtrar then
    AcortarTramosFiltrados(series, umbralFiltro);


  NDatos := series[0].n;

  A := TMatR.Create_Init(length(series), length(series));
  // construimos la matriz de covarianzas
  // como es simétrica lleno solo el triangulo superior
  for k := 1 to A.nf do
    for j := k to A.nc do
    begin
      // se supone que las series tienen valor esperado NULO
      m := series[k - 1].PEV(series[j - 1]) / NDatos;
      A.pon_e(k, j, m);
    end;

  B := A.Raiz_Cholesky;
  if B = nil then
    B := A.RaizPorPotenciaIterada( DimRes, true );
  A.Free;
  Result := B;
end;



function descuadrador(var series: TDAOfVectR; filtrar: boolean;
  umbralFiltro: NReal): TMatR;
const
  MaxNIters = 1000;

var
  NSems, NSeries, NDescuadres: integer;

var
  x_series, x_autovects: TVectR;
  xs_series, xs_autovects: TVectR;
  autovects: TDAOfVectR;
  autovals: array of double;
  convergio: array of boolean;
  kvect: integer;
  NAutovects: integer;
  resB: TMatR;

var
  sal{, f}: textfile;
  //  r: string;
  //  ksem: integer;
  //  ap_b,ap_p,ap_s: double;

  k, j: integer;
  me2: double;

  buscando: boolean;

  descuadrando: boolean;
  niter: integer;
  factorCambioNorma: NReal;

  iserie: integer;

  varianzas: TVectR;

  sb2: NReal;

begin
  (*** OJO NO USE ESTE METODO ***)


  // SI la orden es filtrar, acortamos las series
  // quitando los tramos en los que actuó el filtro.
  if Filtrar then
    AcortarTramosFiltrados(series, umbralFiltro);

  // más vale hacer esto después de acortar las series.
  NSeries := length(Series);
  NSems := Series[0].n;

  // calculamos las varianzas
  varianzas := TVectR.Create_Init(NSeries);
  for iserie := 1 to NSeries do
    varianzas.pv[iserie] := series[iserie - 1].varianza;

  NDescuadres := NSeries;

  setlength(autovects, NDescuadres);
  setlength(autovals, NDescuadres);
  setlength(convergio, NDescuadres);


  for k := 1 to NDescuadres do
    autovects[k - 1] := TVectR.Create_Init(NSems);

  x_series := TVectR.Create_Init(NSeries);
  x_autovects := TVectR.Create_Init(NDescuadres);
  xs_series := TVectR.Create_Init(NSeries);
  xs_autovects := TVectR.Create_Init(NDescuadres);

  kvect := 1;
  descuadrando := True;

  NAutovects := NDescuadres;

  while (kvect <= NDescuadres) and (descuadrando) do
  begin
    // cargamos un versor cualquiera como candidato
    // a ser el autovalor principal del conjunto de series.
    // elegimos la serie como inicio de iteración, pero no es imperativo.
    autovects[kvect - 1].Copy(Series[kvect - 1]);
    autovects[kvect - 1].hacerunitario;

    // inicializamos variables auxiliares de la iteración
    x_series.Ceros;
    x_autovects.Ceros;
    buscando := True;
    niter := 1;


    while buscando and (niter <= MaxNIters) do
    begin
      // proyecciones sobre las series
      for k := 1 to NSeries do
        xs_series.pon_e(k, series[k - 1].PEV(autovects[kvect - 1]));
      // proyecciones sobre autovectores ya estimados
      for k := 1 to kvect - 1 do
        xs_autovects.pon_e(k, autovects[k - 1].PEV(autovects[kvect - 1]));

      // calculo de variación para dar fin a la iteración
      me2 := (xs_series.distancia2(x_series) + xs_autovects.distancia2(
        x_autovects)) / NSems;
      if (me2 < 1e-14) then
        buscando := False;
      vswap(xs_series, x_series);
      vswap(xs_autovects, x_autovects);
      // formación del vector
      autovects[kvect - 1].ceros;
      for k := 1 to NSeries do
        autovects[kvect - 1].sumRPV(x_series.e(k), series[k - 1]);

      for k := 1 to kvect - 1 do
        autovects[kvect - 1].sumRPV(-autovals[k - 1] * x_autovects.e(k),
          autovects[k - 1]);

      // usamos la raiz de la varianza como distancia
      autovals[kvect - 1] := autovects[kvect - 1].normEuclid;
      // lo hacemos unitario
      autovects[kvect - 1].PorReal(1 / autovals[kvect - 1]);
      Inc(niter);
    end;
    if buscando then
    begin
      descuadrando := False;
      NAutovects := kvect - 1;
    end
    else
    begin
      writeln('me2: ', me2, ' landa: ', autovals[kvect - 1]);
      writeln('niter: ', niter);
      Inc(kvect);
    end;
  end;


(* Escalamos los autovectores para que sean de varianza 1
en lugar de Norma Euclidea 1 *)
  factorCambioNorma := sqrt(NSems);
  for j := 1 to NAutovects do
    autovects[j - 1].PorReal(factorCambioNorma);

(* generalmente NAutovects = NSeries, sería demasiada casualidad
que las muestras dieran con un autovalor NULO *)
  resB := TMatR.Create_Init(NSeries, NAutovects);
  for k := 1 to NSeries do
    for j := 1 to NAutovects do
      resB.pon_e(k, j, series[k - 1].PEV(autovects[j - 1]) / NSems);
(*
 las filas de B son las cordenadas de las series en la base de los
 autovectores.*)
  Result := resB;

  for k := 1 to NSeries do
  begin
    sb2 := resB.Fila(k).ne2;
    resB.Fila(k).PorReal(sqrt(varianzas.e(k) / sb2));
  end;

  (*** IMPRIMIMOS el archivo de control de resultados ****)
  assignfile(sal, 'descuadre.xlt');
  rewrite(sal);
  writeln(sal, 'MATRIZ B ');
  for k := 1 to NSeries do
  begin
    Write(sal, 'serie: ', #9, k);
    for j := 1 to NAutovects do
      Write(sal, #9, resB.e(k, j));
    writelN(sal);
  end;

  writeln(sal);
  Write(sal, 'autovalores:', #9);
  for j := 1 to NAutovects do
    Write(sal, #9, autovals[j - 1]);
  writeln(sal);


  writeln(sal, ' SERIES y AUTOVECTORES ');
  for j := 1 to NSeries do
    Write(sal, #9, 's', j);
  for j := 1 to NAutovects do
    Write(sal, #9, 'v', j);
  writeln(sal);

  for k := 1 to NSems do
  begin
    Write(sal, k);
    for j := 1 to NSeries do
      Write(sal, #9, series[j - 1].e(k));
    for j := 1 to NAutovects do
      Write(sal, #9, autovects[j - 1].e(k));
    writeln(sal);
  end;
  closefile(sal);

end;



function ivertirfiltro(filtro: TVectR; series: array of TVectR;
  kSerie: integer; filtrar: boolean; umbralFiltro: NReal;
  var varianzaDelResultado: NReal; var cntSecuenciasUsadas: integer): TVectR;
var
  k: integer;
  orden: integer;
  res: TVectR;
  a, av: NReal;
  h: integer;
  jSerie: integer;
  NSeries: integer;
  NPuntos: integer;
  flgFiltrado: boolean;

begin
  NSeries := length(series);
  orden := filtro.n div NSeries;
  NPuntos := series[0].n;
  res := TVectR.Create_Init(NPuntos - orden);

  varianzaDelResultado := 0;
  cntSecuenciasUsadas := 0;

  if not Filtrar then
  begin
    for k := 1 + orden to NPuntos do
    begin
      a := series[kSerie - 1].pv[k];
      for jSerie := 1 to NSeries do
        for h := 1 to orden do
          if (k - h) > 0 then
            a := a - filtro.e((h - 1) * NSeries + jSerie) * series[jSerie - 1].pv[k - h];
      res.pv[k - orden] := a;
      varianzaDelResultado := a * a + varianzaDelResultado;
      Inc(cntSecuenciasUsadas);
    end;
  end
  else
  begin
    for k := 1 + orden to NPuntos do
    begin
      a := series[kSerie - 1].pv[k];
      flgFiltrado := a <= umbralFiltro;
      for jSerie := 1 to NSeries do
        for h := 1 to orden do
          if ((k - h) > 0) and (not FlgFiltrado) then
          begin
            av := series[jSerie - 1].pv[k - h];
            if av > umbralFiltro then
              a := a - filtro.e((h - 1) * NSeries + jSerie) * av
            else
              flgFiltrado := True;
          end;

      if flgFiltrado then
        res.pv[k - orden] := umbralFiltro
      else
      begin
        res.pv[k - orden] := a;
        varianzaDelResultado := a * a + varianzaDelResultado;
        Inc(cntSecuenciasUsadas);
      end;
    end;
  end;

  varianzaDelResultado := varianzaDelResultado / (cntSecuenciasUsadas - 1);
  Result := res;
end;


procedure Write_SeriesGaussianas(seriesDeDatos: TSeriesDeDatos);
begin
  seriesDeDatos.WriteToArchi('series_gaussianas.xlt');
end;


procedure Write_FFTSeriesGaussianas(seriesDeDatos: TSeriesDeDatos);
var
  sal: textfile;
  kSerie, kPunto: integer;
  coA, coB: TDAOfNreal;
  A0: NReal;
begin
  setlength(coA, seriesDeDatos.NPuntos div 2);
  setlength(coB, seriesDeDatos.NPuntos div 2);
  WRFFTI01.Init(seriesDeDatos.NPuntos);
  for kSerie := 1 to seriesDeDatos.NSeries do
  begin
    WRFFTF01.FFTF(seriesDeDatos.Series[kSerie - 1].pv[1], A0, coA[0], coB[0]);
    assignfile(sal, 'FFT_seriegaussiana_' + IntToStr(kSerie) + '.txt');
    rewrite(sal);
    writeln(sal, 'A0: ', A0);
    writeln(sal, 'k', #9, 'CA', #9, 'CB');
    for kPunto := 0 to high(coA) do
      writeln(sal, kPunto + 1, #9, coA[kPunto], #9, coB[kPunto]);
    closefile(sal);
  end;
  WRFFTI01.done;
  setlength(coA, 0);
  setlength(coB, 0);
end;



function Analizar_Y_AX_B(archi: string; // ARchivo de salida. 'SintetizadorCEGH.txt'
  seriesDeDatos: TSeriesDeDatos;
  NCronicasRuido: integer;
  PrecisionMedida_pu: NReal;
  ordenfiltro: integer; overlapping: integer;
  traslapping: integer; nPuntosPorMiniciclo: integer; horasEntreMuestras: integer;
  FiltrarMenores: boolean; umbralFiltro: NReal; FiltrarAlGaussianizar: boolean;
  umbralFiltroAlGaussianizar: NReal; kMetodoCalculoB: integer;
  NDigitosDeformadores, NDecimalesDeformadores: integer;
  // formato escritura
  NP_Deformadores: integer; // Cantidad de puntos de los deformadores.
  flg_InforParcial: boolean; anular_negativos_hasta: integer =
  0 // ej. si = 4 anula los deformadores donde sean negativos para series 1,..4
  ): TVectR;

var
  //  r: string;
  ruidos: TDAOfVectR;
  kserie: integer;
  k, j, h: integer;
  //  sal: TextFile;
  {$IFDEF CEGH_ENTRADA_SALIDA}
  sintetizadorSimSEE: TModeloCEGH_EntradaSalida;
  {$ELSE}
  sintetizadorSimSEE: TModeloCEGH;
  {$ENDIF}
  nVEred: integer;
  varNoExplicada: NReal;
  d_varNoExplicada: NReal;
  At: TMatR;
  BtB: TMatR;
  res: TVectR;
  DimRes: integer;

begin

  if not flg_InforParcial then
    raise Exception.Create('este modelo está disponible solo con INFORMACION PARCIAL');

  nVEred := seriesDeDatos.NSeries * ordenfiltro;


  // creamos el sintetizadorSimSEE
  {$IFDEF CEGH_ENTRADA_SALIDA}
  sintetizadorSimSEE := TModeloCEGH_EntradaSalida.Create(
    seriesDeDatos.NSeriesX, seriesDeDatos.NSeriesY, seriesDeDatos.nombresSeries,
    ordenfiltro, trunc(seriesDeDatos.rNPPorCiclo), NP_Deformadores,
    horasEntreMuestras, nVEred);
  {$ELSE}
  sintetizadorSimSEE := TModeloCEGH.Create(seriesDeDatos.NSeries,
    seriesDeDatos.nombresSeries, ordenfiltro, trunc(seriesDeDatos.rNPPorCiclo),
    NP_Deformadores, horasEntreMuestras, nVEred);
  {$ENDIF}


  // **********************************************
  // PASO 1) Creamos deformadores y gaussianizamos
  // ----------------------------------------------

  // Creamos los deformadores
  sintetizadorSimSEE.CrearDeformadores(seriesDeDatos,
    overlapping, traslapping, NPuntosPorMiniciclo,
    FiltrarMenores, umbralFiltro, NCronicasRuido, PrecisionMedida_pu );

  // Transformamos las series al espacio gaussiano
  sintetizadorSimSEE.GaussianizarSeries(
    seriesDeDatos,
    FiltrarMenores,
    umbralFiltro,
    filtrarAlGaussianizar,
    umbralFiltroAlGaussianizar, 1, 0);

  // Antes de identificar el filtro, normalizamos las series por las dudas.
  sintetizadorSimSEE.Normalizar(seriesDeDatos, filtrarMenores, umbralFiltro);

  // Escribimos las series gaussianas
  write_SeriesGaussianas(seriesDeDatos);

  // Escribimos archivo con covarianzas(tau)
  seriesDeDatos.WriteCOVARS('covars_k_gaussianas.xlt', umbralFiltro);

  // Escribimos FFT de las series gaussianas
  //  Write_FFTSeriesGaussianas( seriesDeDatos );

  // ================================================


  (**************************************************************)
  (* Identificación del filtro lineal (en el espacio gaussiano) *)
  (*------------------------------------------------------------*)
  // Primero identificamos la matriz A del filtro por mínimos cuadrados
  At := calcmincuad_mrh_Y_AX_B(seriesDeDatos.get_seriesY_cronActiva, seriesDeDatos.get_seriesX_cronActiva,
    ordenfiltro - 1, filtrarMenores, umbralFiltro, BtB);
  SintetizadorSimSEE.A_cte := At.Crear_Transpuesta;
  At.Free;


  res := TVectR.Create_INit(seriesDeDatos.NSeriesY);
  for kSerie := 1 to res.n do
    res.pon_e(kSerie, BtB.e(kSerie, kSerie));

  varNoExplicada := BtB.traza / seriesDeDatos.NSeriesY;

  if kMetodoCalculoB = 0 then
  begin
    BtB.WriteArchiXLT('btb.xlt');
    SintetizadorSimSee.B_cte := BtB.raiz_Cholesky;
    if SintetizadorSimSee.B_cte = nil then
      SintetizadorSimSee.B_cte := BtB.RaizPorPotenciaIterada( DimRes, true );
  end
  else
  begin
    // OJO, como efecto secundario el dscuadrador puede acortar los vectores
    // de ruidos, eliminando los que fueron filtrados.
    if kMetodoCalculoB = 2 then
      SintetizadorSimSee.B_cte :=
        descuadrador_Cholesky(ruidos, FiltrarMenores, umbralFiltro)
    else
      SintetizadorSimSee.B_cte := descuadrador(ruidos, FiltrarMenores, umbralFiltro);
  end;
  BtB.Free;


  // bien ahora vamos a completar la información de reducción de estados.
  for j := 1 to ordenfiltro do
    for k := 1 to seriesDeDatos.NSeriesX do
    begin

      if ordenfiltro > 1 then
        SintetizadorSimSEE.nombreVarE[(k - 1) + (j - 1) * SeriesDeDatos.NSeriesX] :=
          seriesDeDatos.nombresSeriesX[k - 1] + '_' + IntToStr(j)
      else
        SintetizadorSimSEE.nombreVarE[(k - 1) + (j - 1) * SeriesDeDatos.NSeriesX] :=
          seriesDeDatos.nombresSeriesX[k - 1];

      SintetizadorSimSEE.MRed_cte.pon_e(k, (k - 1) * ordenfiltro + j, 1);
      SintetizadorSimSEE.nDiscsVsE[(k - 1) * ordenfiltro + j - 1] := 5;
      setlength(SintetizadorSimSEE.ProbsVsE[(k - 1) * ordenfiltro + j - 1], 5);
      for h := 0 to 4 do
        SintetizadorSimSEE.ProbsVsE[(k - 1) * ordenfiltro + j - 1][h] := 0.2;
    end;

  if anular_negativos_hasta > 0 then
    for k := 1 to anular_negativos_hasta do
      SintetizadorSimSEE.Anular_Negativos_DelDeformador(k);

  SintetizadorSimSEE.WriteToArchi(archi, NDigitosDeformadores,
    NDecimalesDeformadores);
  //   Result := VarNoExplicada;
  Result := res;

end;




function Analizar_FiltroVariable(archi: string;

  // Archivo de salida 'SintetizadorCEGH_mc.txt'
  seriesDeDatos: TSeriesDeDatos;
  NCronicasRuido: integer;
  PrecisionMedida_pu: NReal;
  ordenfiltro: integer; overlapping: integer;
  traslapping: integer; NPuntosPorMiniciclo: integer; horasEntreMuestras: integer;
  FiltrarMenores: boolean; umbralFiltro: NReal; FiltrarAlGaussianizar: boolean;
  umbralFiltroAlGaussianizar: NReal;
  NDigitosDeformadores, NDecimalesDeformadores: integer; // formato escritura
  NP_Deformadores: integer;   // cantidad de puntos usados en la discretización de los deformadores
  flg_InfoParcial: boolean;
  flg_CompletarHuecosConRuidoBlanco: boolean ): TVectR;

var
  k, j, h: integer;
  //  sal: TextFile;

  nVEred: integer;

  sintetizadorSimSEE: TModeloCEGH;

  mcA, mcB: TDAOfMatR;

  fsal: textfile;
  kfil, jcol: integer;
  varNoExplicado: NReal;
  res: TVectR;

  nFilas, nRetardo: integer;
  kSerie: integer;

begin

  nVEred := seriesDeDatos.NSeries * ordenfiltro;

  // creamos el sintetizadorSimSEE
  sintetizadorSimSEE := TModeloCEGH.Create_MultiCiclo(
    seriesDeDatos.NSeries, seriesDeDatos.nombresSeries, ordenfiltro,
    trunc(seriesDeDatos.rNPPorCiclo), NP_Deformadores, horasEntreMuestras, nVERed);


  // **********************************************
  // PASO 1) Creamos deformadores y gaussianizamos
  // ----------------------------------------------

  // Creamos los deformadores
  sintetizadorSimSEE.CrearDeformadores(seriesDeDatos,
    overlapping, traslapping, NPuntosPorMiniciclo,
    FiltrarMenores, umbralFiltro, NCronicasRuido, PrecisionMedida_pu );

  // Transformamos las series al espacio gaussiano
  sintetizadorSimSEE.GaussianizarSeries(
    seriesDeDatos,
    FiltrarMenores,
    umbralFiltro,
    filtrarAlGaussianizar,
    umbralFiltroAlGaussianizar, 1, 0);

  // Antes de identificar el filtro, normalizamos las series por las dudas.
  sintetizadorSimSEE.Normalizar(seriesDeDatos, filtrarMenores, umbralFiltro);

  // Escribimos las series gaussianas
  write_SeriesGaussianas(seriesDeDatos);

  // Escribimos archivo con covarianzas(tau)
  seriesDeDatos.WriteCOVARS('covars_k_gaussianas.xlt', umbralFiltro);

  // Escribimos FFT de las series gaussianas
  //  Write_FFTSeriesGaussianas( seriesDeDatos );

  // ================================================


  (**************************************************************)
  (* Identificación del filtro lineal (en el espacio gaussiano) *)
  (*------------------------------------------------------------*)
  // Primero identificamos la matriz A del filtro por mínimos cuadrados
  res := calcmincuad_mrh_mc(seriesDeDatos.get_series_cronActiva, ordenfiltro,
    filtrarMenores, umbralFiltro, seriesDeDatos.rNPPorCiclo,
    seriesDeDatos.rOffsetCiclo, overlapping, traslapping,
    NPuntosPorMiniciclo, mcA{%H-}, mcB{%H-}, True, seriesDeDatos.nombresSeries,
    flg_InfoParcial, flg_CompletarHuecosConRuidoBlanco, VarNoExplicado{%H-});


  SintetizadorSimSEE.mcA := mcA;
  SintetizadorSimSEE.mcB := mcB;

  assignfile(fsal, 'mab.xlt');
  rewrite(fsal);
  k := 0;
  for kfil := 1 to mcA[k].nf do
  begin
    nFilas:= mcA[k].nf;
    for jcol := 1 to mcA[k].nc do
    begin
      nRetardo:= (( jcol -1 ) div nFilas )+1;
      kSerie:= ( jcol - 1)  mod  nFilas;
      Write(fsal, #9, seriesDeDatos.nombresSeries[kFil-1] + '-' +
        seriesDeDatos.nombresSeries[ kSerie ]+'_'+IntToStr( nRetardo ) );
    end;
  end;
  Write(fsal, #9, '|');


  for kfil := 1 to mcB[k].nf do
    for jcol := 1 to mcB[k].nc do
    begin
      Write(fsal, #9, seriesDeDatos.nombresSeries[kfil - 1] + '-R_' +
        IntToStr( jCol ));
    end;
  writeln(fsal);

  for k := 0 to high(mcA) do
  begin

    writeln('k: ', k);
    Write(fsal, k);
    if mcA[k] <> nil then
    begin
      for kfil := 1 to mcA[k].nf do
        for jcol := 1 to mcA[k].nc do
          Write(fsal, #9, mcA[k].e(kfil, jcol));
      Write(fsal, #9, '|');
      if (mcB[k] <> nil) then
      begin
        for kfil := 1 to mcB[k].nf do
          for jcol := 1 to mcB[k].nc do
            Write(fsal, #9, mcB[k].e(kfil, jcol));
      end
      else
        Write(fsal, #9, 'MCB[' + IntToStr(k) + ']=NIL');
    end;
    writeln(fsal);
  end;
  closefile(fsal);

  Assignfile(fsal, 'matricesA.xlt');
  rewrite(fsal);
  for k := 0 to high(mcA) do
  begin
    writeln(fsal, 'paso: ', #9, k);
    if mcA[k] <> nil then
      mcA[k].WriteXLT(fsal)
    else
      writeln(fsal, 'SISTEMA NO INVERTIBLE');
  end;
  closefile(fsal);


  Assignfile(fsal, 'matricesB.xlt');
  rewrite(fsal);
  for k := 0 to high(mcB) do
  begin
    writeln(fsal, 'paso: ', #9, k);
    if mcB[k] <> nil then
      mcB[k].WriteXLT(fsal)
    else
      writeln(fsal, 'Falló CHOLESKY');
  end;
  closefile(fsal);



  // bien ahora vamos a completar la información de reducción de estados.
  for j := 1 to ordenfiltro do
    for k := 1 to seriesDeDatos.NSeries do
    begin

      if ordenfiltro > 1 then
        SintetizadorSimSEE.nombreVarE[(k - 1) + (j - 1) * SeriesDeDatos.NSeries] :=
          seriesDeDatos.nombresSeries[k - 1] + '_' + IntToStr(j)
      else
        SintetizadorSimSEE.nombreVarE[(k - 1) + (j - 1) * SeriesDeDatos.NSeries] :=
          seriesDeDatos.nombresSeries[k - 1];

      SintetizadorSimSEE.MRed_cte.pon_e(k, (k - 1) * ordenfiltro + j, 1);
      SintetizadorSimSEE.nDiscsVsE[(k - 1) * ordenfiltro + j - 1] := 5;
      setlength(SintetizadorSimSEE.ProbsVsE[(k - 1) * ordenfiltro + j - 1], 5);
      for h := 0 to 4 do
        SintetizadorSimSEE.ProbsVsE[(k - 1) * ordenfiltro + j - 1][h] := 0.2;
    end;


  SintetizadorSimSEE.WriteToArchi(archi,
    NDigitosDeformadores, NDecimalesDeformadores);
  Result := res;
end;






// calcula los deformadores y el filtro óptimo en el espacio gaussiano.
// los lentes son por paso mientras que el filtro es único.
// La versión Analizar2 identifica un filtro para cada paso.
function Analizar(archi: string; // ARchivo de salida. 'SintetizadorCEGH.txt'
  seriesDeDatos: TSeriesDeDatos;
  NCronicasRuido: integer;
  PrecisionMedida_pu: NReal;
  ordenfiltro: integer; overlapping: integer;
  traslapping: integer; nPuntosPorMiniciclo: integer; horasEntreMuestras: integer;
  FiltrarMenores: boolean; umbralFiltro: NReal; FiltrarAlGaussianizar: boolean;
  umbralFiltroAlGaussianizar: NReal; kMetodoCalculoB: integer;
  NDigitosDeformadores, NDecimalesDeformadores: integer;
  // formato escritura
  NP_Deformadores: integer; // Cantidad de puntos de los deformadores.
  flg_InfoParcial: boolean; anular_negativos_hasta: integer =
  0 // ej. si = 4 anula los deformadores donde sean negativos para series 1,..4
  ): TVectR;

var
  //  r: string;
  ruidos: TDAOfVectR;
  kserie: integer;
  k, j, h: integer;
  //  sal: TextFile;
  sintetizadorSimSEE: TModeloCEGH;
  nVEred: integer;
  varNoExplicada: NReal;
  d_varNoExplicada: NReal;
  cntSecuenciasUsadas: integer;
  At, BtB: TMatR;
  res: TVectR;
  filas: integer;
  Ae: TMatR;
  Ap: TMatR;
  f: integer;
  c: integer;
  flg_CorrCorPla: boolean;
  o: integer;
  nseries: integer;
  Vdif: TVectR;
  Ve: TVectR;
  vpc: TVectR;
  Mcegh: TModeloCEGH;
  series: TSeriesDeDatos;
  kpaso: integer;
  filtrar_huecos: boolean;
  valmin: integer;
  idxhuecos: TDAofNInt;
  ek: TMatR;
  Xpk: TMatR;
  archiDatos: string;
  idx: integer;
  prod: extended;
  archiSalidaGauss: string;
  archiSalida: string;
  DimRes: integer;
begin

  nVEred := seriesDeDatos.NSeries * ordenfiltro;


  // creamos el sintetizadorSimSEE
  sintetizadorSimSEE := TModeloCEGH.Create(seriesDeDatos.NSeries,
    seriesDeDatos.nombresSeries, ordenfiltro, trunc(seriesDeDatos.rNPPorCiclo),
    NP_Deformadores, horasEntreMuestras, nVEred);

  // **********************************************
  // PASO 1) Creamos deformadores y gaussianizamos
  // ----------------------------------------------

  // Creamos los deformadores
  sintetizadorSimSEE.CrearDeformadores(seriesDeDatos,
    overlapping, traslapping, NPuntosPorMiniciclo,
    FiltrarMenores, umbralFiltro, NCronicasRuido, PrecisionMedida_pu );

  // Transformamos las series al espacio gaussiano
  sintetizadorSimSEE.GaussianizarSeries(
    seriesDeDatos,
    FiltrarMenores,
    umbralFiltro,
    filtrarAlGaussianizar,
    umbralFiltroAlGaussianizar, 1, 0 );

  // Antes de identificar el filtro, normalizamos las series por las dudas.
  sintetizadorSimSEE.Normalizar(seriesDeDatos, filtrarMenores, umbralFiltro);

  // Escribimos las series gaussianas
  write_SeriesGaussianas(seriesDeDatos);

  // Escribimos archivo con covarianzas(tau)
  seriesDeDatos.WriteCOVARS('covars_k_gaussianas.xlt', umbralFiltro);

  // Escribimos FFT de las series gaussianas
  Write_FFTSeriesGaussianas(seriesDeDatos);

  // ================================================




  (**************************************************************)
  (* Identificación del filtro lineal (en el espacio gaussiano) *)
  (*------------------------------------------------------------*)
  // Primero identificamos la matriz A del filtro por mínimos cuadrados
  At := calcmincuad_mrh(seriesDeDatos.get_series_cronActiva, ordenfiltro, filtrarMenores,
    umbralFiltro, flg_InfoParcial, BtB);
  SintetizadorSimSEE.A_cte := At.Crear_transpuesta;
  At.Free;


  setlength(ruidos, seriesDeDatos.NSeries);
  // inversión de las series por el filtro
  // para tener las gaussianas de entrada
  // El largo de las series de ruidos es NPuntos-Orden pues
  // para los primeros puntos de las series (de 1 a Orden) no hay
  // datos para calcular el ruido.

    (*
    varNoExplicada := 0;
    for kserie := 1 to seriesDeDatos.NSeries do
    begin
      ruidos[kserie - 1] := ivertirfiltro(SintetizadorSimSee.A_cte.fila(kserie),
        seriesDeDatos.series, kserie, filtrarMenores, umbralFiltro,
        d_varNoExplicada, cntSecuenciasUsadas);
      varNoExplicada     := varNoExplicada + d_varNoExplicada / seriesDeDatos.NSeries;
    end;
    *)


  res := TVectR.Create_INit(seriesDeDatos.NSeries);
  for kSerie := 1 to res.n do
    res.pon_e(kSerie, BtB.e(kSerie, kSerie));

  varNoExplicada := BtB.traza / seriesDeDatos.NSeries;

  if kMetodoCalculoB = 0 then
  begin
    BtB.WriteArchiXLT('btb.xlt');
    SintetizadorSimSee.B_cte := BtB.raiz_Cholesky;
    if SintetizadorSimSee.B_cte = nil then
      SintetizadorSimSee.B_cte := BtB.RaizPorPotenciaIterada( DimRes, true );
  end
  else
  begin
    // OJO, como efecto secundario el dscuadrador puede acortar los vectores
    // de ruidos, eliminando los que fueron filtrados.
    if kMetodoCalculoB = 2 then
      SintetizadorSimSee.B_cte :=
        descuadrador_Cholesky(ruidos, FiltrarMenores, umbralFiltro)
    else
      SintetizadorSimSee.B_cte := descuadrador(ruidos, FiltrarMenores, umbralFiltro);
  end;
  BtB.Free;


  // bien ahora vamos a completar la información de reducción de estados.
  for j := 1 to ordenfiltro do
    for k := 1 to seriesDeDatos.NSeries do
    begin

      if ordenfiltro > 1 then
        SintetizadorSimSEE.nombreVarE[(k - 1) + (j - 1) * SeriesDeDatos.NSeries] :=
          seriesDeDatos.nombresSeries[k - 1] + '_' + IntToStr(j)
      else
        SintetizadorSimSEE.nombreVarE[(k - 1) + (j - 1) * SeriesDeDatos.NSeries] :=
          seriesDeDatos.nombresSeries[k - 1];

      //SintetizadorSimSEE.MRed.pon_e(k, (k - 1) * ordenfiltro + j, 1);
      SintetizadorSimSEE.MRed_cte.pon_e(k + (j - 1) * seriesDeDatos.NSeries,
        k + (j - 1) * seriesDeDatos.NSeries, 1);
      SintetizadorSimSEE.nDiscsVsE[(k - 1) * ordenfiltro + j - 1] := 5;
      setlength(SintetizadorSimSEE.ProbsVsE[(k - 1) * ordenfiltro + j - 1], 5);
      for h := 0 to 4 do
        SintetizadorSimSEE.ProbsVsE[(k - 1) * ordenfiltro + j - 1][h] := 0.2;
    end;

  if anular_negativos_hasta > 0 then
    for k := 1 to anular_negativos_hasta do
      SintetizadorSimSEE.Anular_Negativos_DelDeformador(k);

  SintetizadorSimSEE.WriteToArchi(archi, NDigitosDeformadores,
    NDecimalesDeformadores);
  //   Result := VarNoExplicada;
  Result := res;
end;





constructor TanalisisSerialcmd.Create(nombreArchivo:string);
begin
    eArchiSeriesDeDatos := nombreArchivo;
  eArchiCEGH := extractfiledir(nombreArchivo) + '/CEGH_' + extractfilename(nombreArchivo);

  eGradoTendencia := '1';                      // no usado?
  eMinicicloCaracteristico := '24';            // no usado?
  eMinicicloCaracteristicoTendencia := '24';   // no usado?
  eNClusters := '3';                           // no usado?
  eNCronicas := '100';                         // no usado?
  eNCronicasRuido := '1';
  eNDecimalesDesformadores := '3';
  eNDigitosDesformadores := '8';
  eNNeuronasPorCanal := '5';                   // no usado?
  eNRetardos := '1';                           // no usado?
  eNPuntosPorMiniCiclo := '0';
  eNP_Deformadores := '200';
  eOrdenDelFiltro := '1';
  eOrdenESHY := '4';
  eOverlapping := '3';
  ePrecisionMedida := '0.03';
  eSemanaInicioVentanaAnaloga := '27';         // no usado?
  eTraslapping := '0';
  eUmbralAlGaussianizar := '10';
  eUmbralFiltro := '-1111';
  eUmral_calcerrores := '-1111';               // no usado?


  cbAniosAnalogos := false;
  cbCopiarUltimomCicloComoEstadoinicial := false;
  cbFiltradoKTPorIh0:= false;
  cbFiltrarMenores:= true;
  cbFiltroCiclico:= false;
  cb_FiltrarAlGaussianizar:= false;
  cbCurvaAero:= false;
  cb_Filtrarmenores_CalcErrores:= true;
  cbTendenciaExponencial:= false;
  cb_InfoParcial:= false;
  cbCompletarHuecosConRuidoBlanco:= false;

  rgTipoModelo := 0;
  rbg_CalculoB := 0;                      // Algebraica + Cholesky


  lstAniosAnalogos := '1911 1912 1913 1914 1915 1918 1919 1923 1925 1926 1929 1957 1958 1963 1965 1968 1969 1972 1977 1980 1983 1986 1987 1991 1992 1994 2002 2003 2004 2006';

end;


procedure TanalisisSerialcmd.Analizarcmd(Limpieza:boolean);

var
  varNoExplicada: NReal;
  varNoExplicada_Vect: TVectR;
  archi: string;
  kSerie: integer;
  j: integer;
  ih0: NReal;
  dtMuestra: TDateTime;
  anular_negativos_hasta: integer;
  v_nCronicasRuido: integer;
  v_PrecisionMedida, v_UmbralFiltro, v_UmbralFiltroAlGaussianizar: NReal;
  v_OrdenDelFiltro, v_Traslapping: integer;
  v_NPuntosPorMiniCiclo, v_HorasEntreMuestras: integer;
  flg_FiltrarMenores, flg_FiltrarAlGaussianizar, flg_InfoParcial: Boolean;
  v_NDigitosDeformadores, v_NDecimalesDeformadores,
  v_NPuntosDeformador: integer;

begin
  varNoExplicada_Vect := nil;

  if FileExists(eArchiSeriesDeDatos) then
  begin
    if seriesDeDatos <> nil then
      seriesDeDatos.Free;

    seriesDeDatos := TSeriesDeDatos.CreateFromArchi(eArchiSeriesDeDatos);

    if seriesDeDatos.rNPPorCiclo < StrToInt(eNPuntosPorMiniciclo) then
    begin
      writeln(
        'NPuntosPorPeriodo < NPuntosPorMiniciclo; Impongo: NPuntosPorPeriodo = NPuntosPorMniciclo='
        + eNPuntosPorMiniciclo);
      seriesDeDatos.rNPPorCiclo := StrToInt(eNPuntosPorMiniciclo);
    end;

    if cbFiltradoKTPorIh0 then
    begin
      (*** REFILTRO LOS KTs****)
      for j := 1 to seriesDeDatos.NPuntos do
      begin
        dtMuestra := seriesDeDatos.dtMuestra(j);
        Ih0 := RadiacionSolarExtraterrestrePlanoHorizontal_Ih0(
          dtMuestra, -31.430612, -57.90961, -3);
        //     seriesDeDatos.series[4].pon_e( j, Ih0 );
        if Ih0 < 0.2 then
          for kSerie := 0 to 3 do
            seriesDeDatos.series[kSerie].pon_e(j, -1234000);
      end;
      archi := eArchiSeriesDeDatos;
      archi := ChangeFileExt(archi, '.fil');
      seriesDeDatos.WriteToArchi(archi);
    end;

    if self.cbAniosAnalogos then
    begin
      GetAniosAnalogos;
      MascararAniosNoAnalogos(seriesDeDatos, strToFloat(eUmbralFiltro));
    end;

    if not cbFiltroCiclico then
    begin

      if cbFiltradoKTPorIh0 then
        anular_negativos_hasta := 4
      else
        anular_negativos_hasta := 0;

// Pasamos los valores de los campos del formularios a variables antes de llamar
// a la función para facilitar el debugger de errores de conversión.
      v_nCronicasRuido:=  StrToInt( eNCronicasRuido );
      v_PrecisionMedida:= StrToFloat( ePrecisionMedida );
      v_OrdenDelFiltro:= StrToInt(eOrdenDelFiltro);
      v_Traslapping:= StrToInt(eTraslapping);
      v_NPuntosPorMiniCiclo:= StrToInt( eNPuntosPorMiniciclo );
      v_HorasEntreMuestras:= trunc( seriesDeDatos.dtEntreMuestras * 24 + 0.1) ;
      flg_FiltrarMenores:= cbFiltrarMenores ;
      v_UmbralFiltro:= strToFloat(eUmbralFiltro);
      flg_FiltrarAlGaussianizar:= cb_FiltrarAlGaussianizar ;
      v_UmbralFiltroAlGaussianizar:= strToFloat(eUmbralAlGaussianizar);
      v_NDigitosDeformadores:= StrToInt(eNDigitosDesformadores);
      v_NDecimalesDeformadores:= StrToInt(eNDecimalesDesformadores);
      v_NPuntosDeformador:= StrToInt(eNP_Deformadores);
      flg_InfoParcial:= cb_InfoParcial ;

      if rgTipoModelo = 0 then
        varNoExplicada_Vect :=
          Analizar(eArchiCEGH, seriesDeDatos,
          v_nCronicasRuido, v_PrecisionMedida,
          v_OrdenDelFiltro, StrToInt(eOverlapping),
          v_Traslapping, v_NPuntosPorMiniCiclo,
          v_HorasEntreMuestras, flg_FiltrarMenores,
          v_UmbralFiltro, flg_FiltrarAlGaussianizar,
          v_UmbralFiltroAlGaussianizar, self.rbg_calculoB,
          v_NDigitosDeformadores, v_NDecimalesDeformadores,
          v_NPuntosDeformador, flg_InfoParcial,
          anular_negativos_hasta )
      else
        varNoExplicada_Vect :=
          Analizar_Y_AX_B('SintetizadorCEGH_Y_AX_B.txt', seriesDeDatos,
          StrToInt( eNCronicasRuido ), StrToFloat( ePrecisionMedida ),
          StrToInt(eOrdenDelFiltro), StrToInt(eOverlapping),
          StrToInt(eTraslapping), StrToInt(eNPuntosPorMiniciclo),
          v_HorasEntreMuestras, cbFiltrarMenores,
          strToFloat(eUmbralFiltro), cb_FiltrarAlGaussianizar,
          strToFloat(eUmbralAlGaussianizar), self.rbg_calculoB,
          StrToInt(eNDigitosDesformadores), StrToInt(eNDecimalesDesformadores),
          StrToInt(eNP_Deformadores), cb_InfoParcial,
          anular_negativos_hasta);
    end
    else
    begin
      if rgTipoModelo = 0 then
        varNoExplicada_vect := Analizar_FiltroVariable('SintetizadorCEGH_mc.txt',
          seriesDeDatos,
          StrToInt( eNCronicasRuido ), StrToFloat( ePrecisionMedida ),
          StrToInt(eOrdenDelFiltro),
          StrToInt(eOverlapping), StrToInt(eTraslapping),
          StrToInt(eNPuntosPorMiniciclo), v_HorasEntreMuestras,
          cbFiltrarMenores, strToFloat(eUmbralFiltro),
          cb_FiltrarAlGaussianizar, strToFloat(eUmbralAlGaussianizar),
          StrToInt(eNDigitosDesformadores),
          StrToInt(eNDecimalesDesformadores), StrToInt(eNP_Deformadores),
          cb_InfoParcial, cbCompletarHuecosConRuidoBlanco )
      else
        ShowMessage('El método Multi Filtro no está implementado para modelado Y_AX_B');
    end;


    if varNoExplicada_Vect = nil then
      eVarianzaDeLoNoExplicado := FloatToStr(varNoExplicada)
    else
    begin
      eVarianzaDeLoNoExplicado := varNoExplicada_Vect.serialize;
      varNoExplicada_Vect.Free;
      varNoExplicada_Vect := nil;
    end;

    if seriesDeDatos <> nil then
    begin
      seriesDeDatos.Free;
      seriesDeDatos := nil;
    end;
  end
  else
    ShowMessage('Nombre de Archivo Inválido: ' + eArchiSeriesDeDatos);

  if (Limpieza) then
     self.Limpiar;

end;




procedure TanalisisSerialcmd.GetAniosAnalogos;
var
  s: string;
  k: integer;
  anio: integer;
begin
  s := trim(self.lstAniosAnalogos);
  if s = '' then
  begin
    setlength(aniosanalogos, 0);
    exit;
  end;
  setlength(aniosanalogos, 10000);

  k := 0;
  while s <> '' do
  begin
    anio := nextint(s);
    aniosAnalogos[k] := anio;
    Inc(k);
  end;
  setlength(aniosAnalogos, k);

  semanaDeInicio := StrToInt(eSemanaInicioVentanaAnaloga);
  kBuscarDesde := 0;
end;





procedure TanalisisSerialcmd.MascararAniosNoAnalogos(datos: TSeriesDeDatos; mascara: double);
var
  kserie: integer;
  anio, isem, ksem: integer;
begin
  for kserie := 0 to high(datos.get_series_cronActiva) do
  begin
    anio := datos.PM_Anio;
    kBuscarDesde := 0;
    for isem := 1 to datos.series[0].n do
    begin
      // supongo que empiezan las series en la primer semana del año.
      ksem := ((isem - 1) mod 52) + 1;
      if mascarado(anio, ksem) then
        datos.series[kserie].pon_e(isem, mascara);
      if ksem = 52 then
        Inc(anio);
    end;
  end;
end;



function TanalisisSerialcmd.Mascarado(anio, semana: integer): boolean;
var
  anioInicio: integer;
begin
  if semana >= self.semanaDeInicio then
    anioInicio := anio
  else
    anioInicio := anio - 1;
  Result := buscarAnio(anioInicio) < 0;
end;




function TanalisisSerialcmd.buscarAnio(anio: integer): integer;
var
  buscando: boolean;
  kres: integer;
begin
  kres := -1;
  buscando := True;
  while buscando and (kBuscarDesde < length(aniosanalogos)) do
    if aniosanalogos[kBuscarDesde] = anio then
    begin
      buscando := False;
      kres := kBuscarDesde;
    end
    else
    if aniosanalogos[kBuscarDesde] < anio then
      Inc(kBuscarDesde)
    else
      buscando := False;

  Result := kres;
end;

procedure TanalisisSerialcmd.Limpiar;
begin
  self.Limpiar_btb;
  self.Limpiar_series_gaussianas;
  self.Limpiar_covars_k_gaussianas;
  self.Limpiar_FFTSeriesGaussianas;
  self.Limpiar_Matriz_XXT;
end;

procedure TanalisisSerialcmd.Limpiar_btb;
begin
  if FileExists(extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'btb.xlt') then
  deleteFile(extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator +'btb.xlt');
end;

 procedure TanalisisSerialcmd.Limpiar_series_gaussianas;
begin
  if FileExists(extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'series_gaussianas.xlt') then
  deleteFile(extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'series_gaussianas.xlt');
end;


procedure TanalisisSerialcmd.Limpiar_Matriz_XXT;
begin
  if FileExists(extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'Matriz_XXt.xlt') then
  deleteFile(extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'Matriz_XXt.xlt');
end;



procedure TanalisisSerialcmd.Limpiar_FFTSeriesGaussianas;

var
  i:integer;
  nombre: string;
begin
  i:=1;
  nombre:= extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'FFT_seriegaussiana_' + IntToStr(i) + '.txt';
  while (FileExists(nombre)) do
    begin
      deleteFile(nombre);
      i:=1+i;
      nombre:=extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'FFT_seriegaussiana_' + IntToStr(i) + '.txt';
    end;
end;


procedure TanalisisSerialcmd.Limpiar_covars_k_gaussianas;
begin
  if FileExists(extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'covars_k_gaussianas.xlt') then
  deleteFile(extractFiledir(eArchiSeriesDeDatos) + DirectorySeparator + 'covars_k_gaussianas.xlt');
end;

end.
