#!/usr/bin/perl -w

use strict 'vars';

if (!(defined($ARGV[1])))
  {
    die ("syntax: prl nom_de_l_article donnees.dat\n");
  }
my $NomArticle = $ARGV[0];
my $DebutRevTex = "debut.tex";
my $FinRevTex = "fin.tex";
my $FichierDonnees = $ARGV[1];
my $FichierEPS = $FichierDonnees.".eps";
my @Champ;
my @Aimantation;

&ExtraitDonnees($FichierDonnees, \@Champ, \@Aimantation);
&SoutraitMoyenneEtInverse(\@Aimantation);
&CorrigeDerive(\@Champ, \@Aimantation);
&TraceEPS($FichierEPS, \@Champ, \@Aimantation, "magnetic field (Oe)", "magnetization (arb. units.)");


unless (open (OUTFILE, ">".$NomArticle.".tex"))
  {
    die ("impossible de creer le fichier ".$NomArticle.".tex\n");
  }

my $Ligne;
unless (open (INFILE, $DebutRevTex))
  {
    die ("impossible d'ouvrir le fichier ".$DebutRevTex."\n");
  }
while (defined($Ligne = <INFILE>))
  {
    print OUTFILE ($Ligne);
  }
close (INFILE);

print OUTFILE ("\\begin{figure}[!htbp]
\\begin{center}
\\includegraphics[  width=3.25in, keepaspectratio]{".$FichierEPS."}
\\end{center}
\\caption{it deserves a Nobel prize}
\\end{figure}\n");

my @Titres = ("magnetic field (Oe)", "magnetization (arb. units.)");
my @Tableau = (\@Champ, \@Aimantation);
print OUTFILE (&TableauVersRevTex(\@Titres, \@Tableau, "a nice array"));

unless (open (INFILE, $FinRevTex))
  {
    die ("impossible d'ouvrir le fichier ".$FinRevTex."\n");
  }
while (defined($Ligne = <INFILE>))
  {
    print OUTFILE ($Ligne);
  }
close (INFILE);

close (OUTFILE);

my $Commande = "latex ".$NomArticle.".tex";
`$Commande`;
`$Commande`;
$Commande = "dvipdf ".$NomArticle.".dvi ".$NomArticle.".pdf";
`$Commande`;


# recupere les deux colonnes correspondant au champ magnetique et a l'aimantation
#
# $_[0] = nom du fichier contenant les donnees
# $_[1] = reference sur le tableau qui va contenir les valeurs du champ magnetique
# $_[2] = reference sur le tableau qui va contenir les valeurs de l'aimantation

sub ExtraitDonnees
  {
    my $NomFichier = $_[0];
    my $Champ = $_[1];
    my $Aimantation = $_[2];
    unless (open(INFILE, $NomFichier))
      {
	die ("impossible d'ouvrir ".$NomFichier."\n");
      }
    my $Ligne;
    while ((defined($Ligne = <INFILE>)) && (!($Ligne =~ /^measured field \(Oe\)/)))
      {
      }
    while (defined($Ligne = <INFILE>))
      {
	chomp ($Ligne);
	my @TmpValeurs = split (/\t/, $Ligne);
	push (@$Champ, $TmpValeurs[0]);
	push (@$Aimantation, $TmpValeurs[2]);
      }
    close (INFILE);
  }


# trace la courbe dans un fichier eps
# 
# $_[0] = nom du fichier eps a creer
# $_[1] = reference sur le tableau qui va contenir les valeurs a mettre en abscisse
# $_[2] = reference sur le tableau qui va contenir les valeurs a mettre en ordonnee
# $_[3] = legende a porter sur l'axe des abscisses
# $_[4] = legende a porter sur l'axe des ordonnees

sub TraceEPS
  {
    my $FichierEPS = $_[0];
    my $ValeurX = $_[1];
    my $ValeurY = $_[2];
    my $LengendeX = $_[3];
    my $LengendeY = $_[4];
    my $Index = 0;
    my $Valeur;
    my $FichierTempDonnees = &ObtenirNomFichierTemporaire().".dat";
    my $FichierTempGnuplot = &ObtenirNomFichierTemporaire().".p";

    unless (open (OUTFILE, ">".$FichierTempDonnees))
      {
	die ("impossible de creer le fichier temporaire ".$FichierTempDonnees."\n");
      }
    foreach $Valeur (@$ValeurX)
      {
	print OUTFILE ($Valeur." ".$$ValeurY[$Index]."\n");
	$Index++;
      }
    close (OUTFILE);

    unless (open (OUTFILE, ">".$FichierTempGnuplot))
      {
	die ("impossible de creer le fichier temporaire ".$FichierTempGnuplot."\n");
      }
    print OUTFILE ("set size 1.0, 1.0\n");
    if (defined($LengendeX))
      {
	print OUTFILE ("set xlabel \"".$LengendeX."\"\n");
      }
    if (defined($LengendeX))
      {
	print OUTFILE ("set ylabel \"".$LengendeY."\"\n");
      }
print OUTFILE ("set nokey
set terminal postscript eps enhanced \"Helvetica\" 16
set output \"".$FichierEPS."\"
plot \"".$FichierTempDonnees."\" using 1:2 notitle with lines 1
");
    close (OUTFILE);

    `gnuplot $FichierTempGnuplot`;
    unlink($FichierTempGnuplot);
    unlink($FichierTempDonnees);
  }


# construit un tableau en revtex (avec une orientation en colonne) a partir de tableaux de valeurs
#
# $_[0] = reference sur le tableau contenant les titres de chaque colonne
# $_[1] = reference sur le tableau bidimensionnel contenant les donnees en colonne
# $_[2] = legende a associer au tableau 
# valeur de retour = chaine de caractere donnant l'equivalent revtex du tableau bidimensionnel

sub TableauVersRevTex
  {
    my $Titres = $_[0];
    my $Donnees = $_[1];
    my $Legende = $_[2];
    my $RevTex = "\\begin{table*}
\\begin{ruledtabular}
\\begin{tabular}{";
    my $Index1 = 0;
    my $NbrColonnes = $#$Titres + 1;
    while ($Index1 < $NbrColonnes)
      {
	$RevTex .= "c";
	$Index1++;
      }
    $RevTex .= "}\n";

    $RevTex .= join (" & ", @$Titres);
    $RevTex .= "\\\\ \\hline\n";

    my $ReferenceTableau = $$Donnees[0];
    my $NbrLignes = $#$ReferenceTableau + 1;
    my $Index2 = 0;
    while ($Index2 < $NbrLignes)
      {
	$ReferenceTableau = $$Donnees[0];
	$RevTex .= $$ReferenceTableau[$Index2];
	$Index1 = 1;
	while ($Index1 < $NbrColonnes)
	  {
	    $ReferenceTableau = $$Donnees[$Index1];
	    $RevTex .= " & ".$$ReferenceTableau[$Index2];
	    $Index1++;	
	  }	
	$RevTex .= "\\\\ \n";	
	$Index2++;
      }

    $RevTex .= "\\end{tabular}
\\end{ruledtabular}
\\caption{".$Legende."}
\\end{table*}\n";
    return $RevTex;
  }

# calcul la valeur moyenne d'un tableau puis la soustrait et multiplie par -1
#
# $_[0] = reference sur le tableau a modifier

sub SoutraitMoyenneEtInverse
  {
    my $Tableau = $_[0];
    my $ValeurMoyenne = 0.0;
    my $Valeur;
    foreach $Valeur (@$Tableau)
      {
	$ValeurMoyenne += $Valeur;
      }
    $Valeur = 0;
    $ValeurMoyenne /= ($#$Tableau + 1);
    while ($Valeur <= $#$Tableau)
      {
	$$Tableau[$Valeur] = - $ValeurMoyenne + $$Tableau[$Valeur];
	$Valeur++;
      }
  }

# corrige la derive du signal
#
# $_[0] = reference sur le tableau qui contient les valeurs du champ magnetique
# $_[1] = reference sur le tableau qui va contient les valeurs de l'aimantation

sub CorrigeDerive
  {
    my $Champ = $_[0];
    my $Aimantation = $_[1];

    my $Pente1;
    my $Decalage1;
    my $Pente2;
    my $Decalage2;

    my $Index = 0;
    my $Valeur;
    my @TableauXTemp;
    my @TableauYTemp;
    foreach $Valeur (@$Champ)
      {
	if ($Valeur > 0.1)
	  {
	    push (@TableauXTemp, $Valeur);
	    push (@TableauYTemp, $$Aimantation[$Index]);
	  }
	++$Index;
      }
    &RegressionLineaire(\@TableauXTemp, \@TableauYTemp, \$Pente1, \$Decalage1);

    @TableauXTemp = ();
    @TableauYTemp = ();
    $Index = 0;
    foreach $Valeur (@$Champ)
      {
	if ($Valeur < -0.1)
	  {
	    push (@TableauXTemp, $Valeur);
	    push (@TableauYTemp, $$Aimantation[$Index]);
	  }
	++$Index;
      }
    &RegressionLineaire(\@TableauXTemp, \@TableauYTemp, \$Pente2, \$Decalage2);

    $Pente1 = 0.5 * ($Pente1 + $Pente2);
    $Decalage1 = 0.5 * ($Decalage1 + $Decalage2);
    $Index = 0;
    foreach $Valeur (@$Champ)
      {
	$$Aimantation[$Index] -=  ($Pente1 * $Valeur) + $Decalage1;
	++$Index;
      }

  }

# donne un nom pour un fichier temporaire (sans extension)
#
# valeur de retour = nom de fichier

sub ObtenirNomFichierTemporaire
  {
    return "tmp".time();
  }

# trouve les coefficients d'une regression lineaire
#
# $_[0] = reference sur le tableau qui va contenir les valeurs a mettre en abscisse
# $_[1] = reference sur le tableau qui va contenir les valeurs a mettre en ordonnee
# $_[2] = reference sur la pente de la regression lineaire
# $_[3] = reference sur l'ordonnee a l'origine de la regression lineaire

sub RegressionLineaire
  {
    my $ValeurX = $_[0];
    my $ValeurY = $_[1];
    my $Pente = $_[2];
    my $Decalage = $_[3];
    
    my $SommeX = 0;
    my $SommeY =0; 
    my $SommeX2 = 0;
    my $SommeXY = 0;
    my $Index = 0;
    while ($Index <= $#$ValeurX)
      {
	$SommeX += $$ValeurX[$Index];
	$SommeY += $$ValeurY[$Index];
	$SommeXY += $$ValeurX[$Index] * $$ValeurY[$Index];
	$SommeX2 += $$ValeurX[$Index] * $$ValeurX[$Index];
	$Index++;
      }

    $$Pente = ((($#$ValeurX + 1) * $SommeXY) - ($SommeX * $SommeY)) / ((($#$ValeurX + 1) * $SommeX2) - ($SommeX * $SommeX));
    $$Decalage = (($SommeY * $SommeX2) - ($SommeX * $SommeXY)) / ((($#$ValeurX + 1) * $SommeX2) - ($SommeX * $SommeX));
  }
