{+doc
+NOMBRE: ucalibrarconopronosticos
+CREACION: 2011-11-22
+AUTORES: rch
+REGISTRO:
+TIPO: Unidad Pascal.
+PROPOSITO:procedimiento de calibración de un cono de pronosticos
+PROYECTO:SimSEE

+REVISION:
+AUTOR:
+DESCRIPCION:
-doc}
unit ucalibrarconopronosticos;

{$mode delphi}

{x$DEFINE IMPONGA_FECHAINICONO_SIM}


interface

uses
{$IFDEF CALIBRAR_PRONOSTICOS_TRAZOSXY}
  Graphics, utrazosxy, autoesca,
{$ENDIF}
  uauxiliares, Math, Dialogs,
  umodelosintcegh, upronostico, xmatdefs, ufechas,
  ucosaConNombre, ucosa,
  Classes, SysUtils, matreal, uFuenteSintetizador, usalasdejuego;


(*+doc
Este procedimiento recibe un modelo CEGH y una descripción de los pronosticos asociados
a sus bornes de salida tal como es utilizado porp las FuentesSintetizador.
Si bien los pronosticos pueden especificar la Probabilidad de Excedencia de la GUIA este
procedimiento ignora dicha PE y calcula los vectores "sesgos" y "factor" para lograr
un cono centrado sobre la guía. Se entiende por "Centrado" que la guía tenga probabilidad
de excedencia 50% en el cono.
-doc*)
procedure CalibrarConoCentrado(cegh: TModeloCEGH; escenarios: TEscenarioDePronosticos;
  fechaIniSim: TFecha);

type
(*+doc
Esta clase permite calcular las series de un cono de pronóstico dado un modelo CEGH, un pronótico para una fecha
de inicio. La determinación del cono se hace mediante una simulación de la salida del CEGH de la cantidad de
crónicas especificadas en NCronicas. La simulación se realiza desde FechaIniSim y se finaliza en FechaFinSim
-doc*)
  TSeriesConoPronostico = class
    NPasosT: integer;

    speInf, spe50, speSup: TMatR;
    sVE: TMatR;
    fcegh: TFuenteSintetizadorCEGH; // referencia a la fuente de creación

    pe_inf, pe_sup: NReal;

    constructor CreateFromSim(idHilo: integer; fcegh: TFuenteSintetizadorCEGH;
      fechaIniSim, fechaFinSim: TFecha; NCronicas: integer; pe_inf, pe_sup: NReal);
    procedure Free;
    {$IFDEF CALIBRAR_PRONOSTICOS_TRAZOSXY}
    procedure plot(Sender: TComponent);
    {$ENDIF}
  end;




implementation

// Inicializa el estado X a partir de las guias gaussianas de un escenario.
// Si no hay suficientes valores en las guias asume un CERO.
procedure CargarEstadoCompleto(X: TVectR; aEscenario: TPronosticos; NRetardos: integer);
var
  kRetardo, iSerie: integer;
  xdet: NReal;
begin
  for kretardo := 0 to (NRetardos - 1) do
  begin
    for iSerie := 1 to aEscenario.NSeries do
    begin
      xdet := aEscenario[iSerie-1].fguia_extendida_(aEscenario[iSerie-1].guia_eg, (NRetardos - 1) - kretardo, 0);
      X.pon_e(kRetardo * aEscenario.NSeries + iSerie, xDet);
    end;
  end;
end;

procedure ActualizamosEstado(X, Xs: TVectR);
var
  k: integer;
  NSeries: integer;
begin
  NSeries := Xs.n;
  for k := X.n downto (NSeries + 1) do
    X.pon_e(k, X.e(k - NSeries));
  for k := 1 to NSeries do
    X.pon_e(k, Xs.e(k));
end;

procedure CalibrarConoCentrado(cegh: TModeloCEGH; escenarios: TEscenarioDePronosticos;
  fechaIniSim: TFecha);
var
  NSeries, NEscenarios: integer;

  aEscenario: TPronosticos;
  aProno: TPronostico;

  // auxiliares para cálculo de aperturas
  AperturaRestantePorPaso_pu, AperturaInicial_pu: NReal;

  j: integer; // indice general.

  kSerie, kEscenario, kPaso: integer;

  ydet, xdet: NReal;
  fecha: TFecha;

  jbase: integer;

  jcol: integer;

  X, Xs: TVectR;

  kselector: integer;

  // Largo máximo de sesgos a generar.
  Max_NPCC_NPCL: integer;

  xs_guia: NReal;

begin

  escenarios.prepararse(cegh.durPasoDeSorteoEnHoras);
  NEscenarios := escenarios.Count;
  NSeries := cegh.nBornesSalida;


  for kEscenario := 0 to NEscenarios - 1 do
  begin
    aEscenario := escenarios[kEscenario];

    if aEscenario.fechaIniCono = nil then
      aEscenario.fechaIniCono := TFecha.Create_Dt(fechaIniSim.dt)
    else if aEscenario.fechaIniCono.dt = 0 then
      aEscenario.fechaIniCono.dt := fechaIniSim.dt;
  end;


  // ajustamos dimensiones y limpiamos sesgos y factor
  for kEscenario := 0 to NEscenarios - 1 do
  begin
    aEscenario := escenarios[kEscenario];
    for kSerie := 0 to NSeries - 1 do
    begin
      aProno := aEscenario[kSerie];
      if (cegh.nRetardos + aProno.NPCC) > length(aProno.guia) then
        aProno.NPCC := max(0, length(aProno.guia) - cegh.nRetardos);

      setlength(aProno.sesgo, aProno.NPCC + aProno.NPLC);
      vclear(aProno.sesgo);
      setlength(aProno.factor, aProno.NPSA + aProno.NPAC);
      vclear(aProno.factor);
    end;
  end;

  // llenamos los factores de apertura del cono
  // hasta NPSA dejamos los ceros y a partir de ahí abrimos el cono aumentando
  // linealmente el factor.
  for kEscenario := 0 to NEscenarios - 1 do
  begin
    aEscenario := escenarios[kEscenario];
    for kSerie := 0 to NSeries - 1 do
    begin
      aProno := aEscenario[kSerie];

      AperturaInicial_pu := aProno.AperturaInicial_pu;
      if aProno.NPAC > 0 then
        AperturaRestantePorPaso_pu := max(0.0, 1 - AperturaInicial_pu) / aProno.NPAC
      else
        AperturaRestantePorPaso_pu := 0;

      for j := 0 to aProno.NPSA - 1 do
        aProno.factor[j] := AperturaInicial_pu;
      for j := max(0, aProno.NPSA) to high(aProno.factor) do
        aProno.factor[j] := (j - aProno.NPSA) * AperturaRestantePorPaso_pu +
          AperturaInicial_pu;

    end;
  end;



  // ahora creamos la imagen de las guías de los pronósticos en el espacio
  // gaussiano.

  for kEscenario := 0 to NEscenarios - 1 do
  begin
    aEscenario := escenarios[kEscenario];
    for kSerie := 0 to NSeries - 1 do
    begin
      aProno := aEscenario[kSerie];
      setlength(aProno.guia_eg, length(aProno.guia));

      fecha := TFecha.Create_Clone(aProno.escenario.fechaIniCono);

      // retrocedemos para la cantidad de retardos por la duración del paso de sorteo.
      fecha.addHoras(-(cegh.nRetardos - 1) * cegh.durPasoDeSorteoEnHoras);

      for kpaso := 0 to high(aProno.guia_eg) do
      begin
        ydet := aProno.guia[kpaso];
        kselector := cegh.kSelectorDeformador(fecha);
        xdet := cegh.xTog(ydet, kSerie + 1, kselector + 1);
        aProno.guia_eg[kpaso] := xdet;
        fecha.addHoras(cegh.durPasoDeSorteoEnHoras);
      end;
      fecha.Free;

    end;
  end;




  // ahora, proyectamos la salida del filtro para cada serie conociendo
  // los estados anteriores y la diferencia entre el proyectado y el valor
  // siguiente en los determinismos gaussianos es el sesgo en la fuente.

  // Vectores para soporte del estado y su proyección
  X := TVectR.Create_Init(nSeries * cegh.NRetardos);
  Xs := TVectR.Create_Init(nSeries);

  for kEscenario := 0 to NEscenarios - 1 do
  begin
    aEscenario := escenarios[kEscenario];

    // Determinación de la guia de sesgos más larga e inicialización de los
    // estados del cálculo
    Max_NPCC_NPCL := 0;

    for kSerie := 0 to NSeries - 1 do
    begin
      aProno := aEscenario[kSerie];
      if aProno.NPCC + aProno.NPLC > Max_NPCC_NPCL then
        Max_NPCC_NPCL := aProno.NPCC + aProno.NPLC;
    end;


    if cegh.A_cte = nil then
      // Necesita calcular kselector para seleccionar matriz mcA
    begin
      // neceisto la fecha para calcular el kSelector
      fecha := TFecha.Create_Clone(aProno.escenario.fechaIniCono);
      // retrocedemos para la cantidad de retardos por la duración del paso de sorteo.
      fecha.addHoras(-cegh.NRetardos * cegh.durPasoDeSorteoEnHoras);
    end;

    jbase := cegh.NRetardos - 1;

    for kpaso := 0 to Max_NPCC_NPCL - 1 do
    begin
      if cegh.A_cte = nil then
        // Necesita calcular kselector para seleccionar matriz mcA
      begin
        kselector := cegh.kSelectorDeformador(fecha);
        fecha.addHoras(cegh.durPasoDeSorteoEnHoras);
      end;

      // Cargamos el vector de estado
      if kPaso = 0 then
        CargarEstadoCompleto(X, aEscenario, cegh.NRetardos)
      else
        ActualizamosEstado(X, Xs);

      // Proyectamos la salida del filtro A
      if cegh.A_cte <> nil then
        cegh.A_cte.Transformar(Xs, X)
      else
        cegh.mcA[kSelector].Transformar(Xs, X);

      for jCol := 1 to NSeries do
      begin
        aProno := aEscenario[jCol - 1];
        if kPaso < aProno.NPCC then
        begin
          xs_guia := aProno.fguia_extendida_(aProno.guia_eg, jbase + 1, 0);
          aProno.sesgo[kPaso] := xs_guia - Xs.e(jCol);
          Xs.pon_e(jCol, xs_guia);
        end
        else if kPaso < (aProno.NPCC + aProno.NPLC) then
        begin
          if (aProno.NPLC > 0) and (aProno.NPCC > 0) then
            aProno.sesgo[kPaso] :=
              aProno.sesgo[aProno.NPCC - 1] *
              (1.0 - (kPaso + 1 - aProno.NPCC) / aProno.NPLC);

          // corrigo la proyección acorde con el sesgo
          xs_guia := Xs.e(jCol) + aProno.sesgo[kPaso];
          Xs.pon_e(jCol, xs_guia);
        end;
        // else ... ya terminó la guia de sesgos y dejo el Xs tal cual
      end;
      Inc(jbase);
    end;

    if cegh.A_cte = nil then
      fecha.Free;

    X.Free;
    Xs.Free;
  end;
end;



var

  //Es un arreglo de boneras, donde cada bornera es una matriz
  //Las filas de esta matriz son los pasos y las columnas las cronicas
  preview_datos: array of TMatR;
  preview_fuente: TFuenteSintetizadorCEGH;
  preview_kCronica, preview_jPaso, preview_nseries, preview_DimEstadoReducido: integer;
  preview_despBornera: integer; // desplazamiento en la bornera para acceder a la salida

  // del filtro en el mundo real. = nSeries + (nSeries*NRetardos)
  preview_NCronicas, preview_NPasos: integer;
  {$IFDEF CALIBRAR_PRONOSTICOS_TRAZOSXY}
  trx: array of TfrmDllForm;

  {$ENDIF}

procedure preview_inicioCronica;
begin
  preview_jPaso := 1;
  Inc(preview_kCronica);
end;

procedure preview_finpaso;
var
  jBornera, j: integer;
  MRed: TMatR;
  kSel: integer;
begin

  for jBornera := 0 to preview_nseries - 1 do
  begin
    preview_datos[jBornera].pon_e(preview_jPaso, preview_kCronica,
      preview_fuente.bornera[preview_despBornera + jBornera]);
  end;


  if preview_DimEstadoReducido > 0 then
  begin
    if preview_fuente.datosModelo_Opt.A_cte <> nil then
      MRed := preview_fuente.datosModelo_Opt.MRed_cte
    else
    begin
      kSel := preview_fuente.kSelectorDesformador(
        preview_fuente.datosModelo_Opt, preview_fuente.globs.FechaInicioDelpaso);
      MRed := preview_fuente.datosModelo_Opt.MRed_mc[kSel];
    end;

    for j := 0 to preview_DimEstadoReducido - 1 do
    begin
      preview_fuente.ReducirEstado(preview_fuente.XRed, preview_fuente.jPrimer_X_x,
        preview_fuente.datosModelo_Opt, MRed, preview_fuente.Bornera);
      preview_datos[preview_nseries + j].pon_e(preview_jPaso, preview_kCronica,
        preview_fuente.XRed[j]);
    end;

  end;
  Inc(preview_jPaso);
end;



constructor TSeriesConoPronostico.CreateFromSim(idHilo: integer;
  fcegh: TFuenteSintetizadorCEGH; fechaIniSim, fechaFinSim: TFecha;
  NCronicas: integer; pe_inf, pe_sup: NReal);

var
  durpos: TDAOfNReal;
  jPaso, kSerie: integer;
  jpeInf, jpe50, jpeSup: integer;
  vdatos: TVectR;

  sala: TSalaDeJuego; // auxiliar para la calibración

  kCronica: integer;
  sal: textfile;
  old_dir: string;

  CatalogoRefs: TCatalogoReferencias;
begin
  inherited Create;

  old_dir := getcurrentdir;

  fcegh.WriteToArchi('fcegh_calibrador.txt');

  self.fcegh := fcegh;

  self.pe_inf := pe_inf;
  self.pe_sup := pe_sup;


  setlength(durpos, 1);
  durpos[0] := fcegh.datosModelo_Sim.durPasoDeSorteoEnHoras;

  // creamos un clon para que cuando haga el FREE de la Sala no se me pierda
  // la fuente.
  CatalogoRefs := TCatalogoReferencias.Create;
  preview_fuente := fcegh.Create_Clone(CatalogoRefs, idHilo) as
    TFuenteSintetizadorCEGH;

  sala := TSalaDeJuego.Create(fcegh.capa, 'Calibrador',
    // rango de simulación
    fechaIniSim, fechaFinSim, TFecha.Create_Dt(0),
    // rango de optimización (pongo lo mismo que sim - no importa )
    fechaIniSim, fechaFinSim, durpos);

  sala.setDirCorrida('_calibrador_.ese');

  //Inicializamos todas las variables
  preview_NPasos := sala.globs.calcNPasosSim;
  preview_kCronica := 0;

  preview_nseries := fcegh.datosModelo_Sim.nBornesSalida;
  preview_DimEstadoReducido := fcegh.datosModelo_Sim.MRed_cte.nf;

  preview_despBornera := fcegh.dim_RB + fcegh.dim_Wa +
    fcegh.datosModelo_Sim.nRetardos * preview_nseries;

  NPasosT := preview_NPasos;
  preview_NCronicas := NCronicas;

  speInf := TMatR.Create_Init(preview_NSeries + preview_DimEstadoReducido,
    preview_NPasos);
  spe50 := TMatR.Create_Init(preview_NSeries + preview_DimEstadoReducido,
    preview_NPasos);
  speSup := TMatR.Create_Init(preview_NSeries + preview_DimEstadoReducido,
    preview_NPasos);
  sVE := TMatR.Create_Init(preview_NSeries + preview_DimEstadoReducido,
    preview_NPasos);

  sala.globs.procNot_InicioCronica := preview_inicioCronica;
  sala.globs.procNot_FinPaso := preview_finpaso;


  //Inicializo array para el tamaño de series
  setlength(preview_datos, preview_nseries + preview_DimEstadoReducido);
  //Inicializo matriz como num de pasos x num de cronicas
  for kSerie := 0 to high(preview_datos) do
  begin
    preview_datos[kSerie] := TMatR.Create_Init(preview_NPasos, preview_NCronicas);
  end;

  //Agregamos fuente a la sala
  preview_fuente.nombreArchivoModelo:=fcegh.nombreArchivoModelo;
  preview_fuente.nombreArchivoDatosHistoricos:= fcegh.nombreArchivoDatosHistoricos;
  preview_fuente.nombreArchivoModeloAuxiliar:=fcegh.nombreArchivoModeloAuxiliar;
  sala.listaFuentes_.Add(preview_fuente);

  //Agregamos los archivos a la sala
  sala.archs.Add(fcegh.nombreArchivoModelo);
  sala.archs.Add(fcegh.nombreArchivoDatosHistoricos);
  sala.archs.Add(fcegh.nombreArchivoModeloAuxiliar);

  CatalogoRefs.resolver_referenciasDeArch(sala.archs);


  if CatalogoRefs.referenciasSinResolver > 0 then
  begin
    CatalogoRefs.DumpReferencias('errRefs.txt');
    raise Exception.Create(
      'TSeriesConoPronostico.CreateFromSim - Quedan referencias sin resolver');
  end;

  CatalogoRefs.Free;

  (**** OJO hago como que optmicé para que exista globs.CF ****)
  sala.inicializarOptimizacion_subproc01;
  sala.inicializarOptimizacion_subproc02_(nil, nil);
  sala.globs.abortarSim := False;
  sala.globs.NCronicasSim := NCronicas;
  sala.globs.semilla_inicial_sim := 31;
  // !!!!!!!!!!!!! SIMULAR !!!!!!!!!!!!!!!!!!
  setSeparadoresGlobales; // para que escriba en global
  sala.Simular(0, True);
  setSeparadoresLocales;
  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  jpeInf := min(trunc(pe_inf * NCronicas) + 1, NCronicas);
  jpe50 := min(trunc(0.5 * NCronicas) + 1, NCronicas);
  jpeSup := min(trunc(pe_sup * NCronicas) + 1, NCronicas);


  assignfile(sal, 'ucalibrador.xlt');
  rewrite(sal);
  writeln(sal, 'NSeries: ', preview_NSeries);
  writeln(sal, 'NPasos: ', preview_NPasos);
  writeln(sal, 'DimEstadoReducido: ', preview_DimEstadoReducido);

  for kSerie := 1 to length(preview_datos) do
  begin
    writeln(sal, 'Serie: ', kSerie);
    for jPaso := 1 to preview_NPasos do
    begin
      Write(sal, jPaso);
      //datos[kSerie][jPaso][jCronica]
      vdatos := preview_datos[kSerie - 1].Fila(jPaso);
      for kCronica := 1 to vdatos.n do
        Write(sal, #9, vdatos.e(kCronica));
      writeln(sal);
    end;
    writeln(sal);
  end;

  writeln(sal, '**********CONO RESUMEN*********');
  writeln(sal, 'jpeInf: ', jpeInf, ', jpe50: ', jpe50, ', jpeSup: ', jpeSup);

  //Tenemos que ordenar los vectores de la matriz para poder imprimir el cono
  for jPaso := 1 to preview_NPasos do
  begin
    Write(sal, jPaso);
    for kSerie := 1 to length(preview_datos) do
    begin
      //datos[kSerie][jPaso][jCronica]
      vdatos := preview_datos[kSerie - 1].Fila(jPaso);
      vdatos.Sort(True);

      sVE.pon_e(kSerie, jPaso, vdatos.promedio);
      speInf.pon_e(kSerie, jPaso, vdatos.e(jpeInf));
      spe50.pon_e(kSerie, jPaso, vdatos.e(jpe50));
      speSup.pon_e(kSerie, jPaso, vdatos.e(jpeSup));

      Write(sal, #9, sVE.e(kSerie, jPaso));
      Write(sal, #9, speInf.e(kSerie, jPaso));
      Write(sal, #9, spe50.e(kSerie, jPaso));
      Write(sal, #9, speInf.e(kSerie, jPaso));
    end;
    writeln(sal);
  end;

  closefile(sal);

  sala.Free;
  preview_fuente := nil; // ya la liberó la sala.
  for kSerie := 0 to high(preview_datos) do
    preview_datos[kSerie].Free;
  setlength(preview_datos, 0);

  setcurrentdir(old_dir);
end;

procedure TSeriesConoPronostico.Free;
begin
  speInf.Free;
  spe50.Free;
  speSup.Free;
  sVE.Free;
end;



{$IFDEF CALIBRAR_PRONOSTICOS_TRAZOSXY}
procedure TSeriesConoPronostico.plot(Sender: TComponent);
var
  kSerie, jPaso: integer;
  colores: array of TColor;
  nombreBorne: string;

  minVal, maxVal, dVal: NReal;

  NDivY: integer;
  guia: TDAOfNReal;
  jPasoGuia, jPasoGuia_Ultimo: integer;

  iserie_VE, iserie_Guia, iserie_pe05, iserie_pe50, iserie_pe95: integer;

begin
  if NPasosT <= 0 then
  begin
    ShowMessage('No hay cono de pronósticos especificado.');
    exit;
  end;

  (*
  if length(trx) <> 0 then
    for kSerie := 0 to high(trx) do
      if trx[kSerie] <> nil then
        trx[kSerie].Close;
    *)

  SetLength(trx, preview_nseries + preview_DimEstadoReducido);
  //Tamaño del vector de graficos
  //Creo un array con los colores para todas las posibles series
  setlength(colores, 12);
  colores[0] := clBlue;
  colores[1] := clOlive;
  colores[2] := clTeal;
  colores[3] := clGreen;
  colores[4] := clNavy;
  colores[5] := clPurple;
  colores[6] := clBlack;
  colores[7] := clGray;
  colores[8] := clLime;
  colores[9] := clFuchsia;
  colores[10] := clMaroon;
  colores[11] := clRed;

  //Comienza loop de imprimir
  for kSerie := 0 to preview_nseries + preview_DimEstadoReducido - 1 do
  begin

    if kSerie < preview_nseries then
      nombreBorne := fcegh.NombresDeBornes_Publicados[kSerie]
    else
      nombreBorne := fcegh.datosModelo_Sim.nombreVarE[kSerie - preview_nseries];


    minVal := speInf.fila(kSerie + 1).minval;
    maxVal := speSup.fila(kSerie + 1).maxval;

    NDivY := 8;
    Escala125N(minVal, maxVal, dVal, NDivY, 1);

    (*
    if trx[kSerie] <> nil then
      trx[kSerie].Close;
     *)

    trx[kSerie] := TfrmDllForm.Create(Sender);

    iserie_VE := 1;
    trx[kSerie].CrearDiagramaXY(
      nombreBorne, // Nombres
      NPasosT,      // MaxNPuntos
      False,       // ciruclar
      'paso',         // nombre_sx
      'VE',  // nombre_sy1: pchar;
      colores[0],  //  color_sy1: TColor;
      1, NPasosT,   //  x1, x2,
      minVal, maxVal, //y1, y2
      10, NDivY        // NDivX, NDivY
      );

    //    trx[kSerie].nilOnClose := @trx[kSerie];

    trx[kSerie].Show;

    //Creo las series
    if kSerie < preview_nseries then
      iserie_Guia := trx[kSerie].CrearSerieXY('Guía', NPasosT, False,
        colores[1], TM_Cuadrado, colores[1], colores[1], 3);

    iserie_pe05 := trx[kSerie].CrearSerieXY('pe_' +
      FloatToStr(trunc(self.pe_inf * 100 + 0.5)) + '%', NPasosT,
      False, colores[2], TM_Triangulo, colores[2], colores[2], 3);
    iserie_pe50 := trx[kSerie].CrearSerieXY('pe_50%', NPasosT, False,
      colores[3], TM_Circulo, colores[3], colores[3], 3);
    iserie_pe95 := trx[kSerie].CrearSerieXY('pe_' +
      FloatToStr(trunc(self.pe_sup * 100 + 0.5)) + '%', NPasosT,
      False, colores[4], TM_Cruz45, colores[4], colores[4], 3);

    trx[kSerie].dbj_gridx;
    trx[kSerie].dbj_gridy;
    trx[kSerie].dbj_borde;
    trx[kSerie].titulo(nombreBorne);
    trx[kSerie].etiquetas_x(0, NPasosT);
    trx[kSerie].etiquetas_y(MinVal, maxVal);
    trx[kSerie].xlabel('PasoT');
    //    trx[kSerie].ylabel('M^3/s');


    if kSerie < preview_nseries then
    begin
      guia := fcegh.escenariosDePronosticos[0][kSerie].guia;
      jPasoGuia := fcegh.datosModelo_Sim.nRetardos - 1;
      jPasoGuia_Ultimo := jPasoGuia + fcegh.escenariosDePronosticos[0][kSerie].NPCC;
    end;

    //Aca se imprimen los valores de cada serie
    for jPaso := 1 to NPasosT do
    begin
      trx[kSerie].tr1.PlotNuevo_x(jPaso);
      trx[kSerie].tr1.PlotNuevo_y(iserie_VE, sve.fila(kserie + 1).e(jPaso));
      if kSerie < preview_nseries then
      begin
        if jPasoGuia <= high(guia) then
          trx[kSerie].tr1.PlotNuevo_y(iserie_Guia, guia[jPasoGuia]);
        Inc(jPasoGuia);
      end;
      trx[kSerie].tr1.PlotNuevo_y(iserie_pe05, speInf.fila(kserie + 1).e(jPaso));
      trx[kSerie].tr1.PlotNuevo_y(iserie_pe50, spe50.fila(kserie + 1).e(jPaso));
      trx[kSerie].tr1.PlotNuevo_y(iserie_pe95, speSup.fila(kserie + 1).e(jPaso));
    end;

  end;//End del loop que imprime cada serie

  SetLength(colores, 0);
end;

{$ENDIF}


procedure AlFinal;
{$IFDEF CALIBRAR_PRONOSTICOS_TRAZOSXY}
var
  k: integer;
  {$ENDIF}
begin
  {$IFDEF CALIBRAR_PRONOSTICOS_TRAZOSXY}
  (*
  if length( trx ) > 0 then
    for k:= 0 to high( trx ) do
      if trx[k] <> nil then
        trx[k].Close;
        *)
  setlength(trx, 0);
  {$ENDIF}
end;

initialization
  preview_datos := nil;
  preview_fuente := nil;
  {$IFDEF CALIBRAR_PRONOSTICOS_TRAZOSXY}
  setlength(trx, 0);
  {$ENDIF}
finalization
  AlFinal;
end.
