{ ============================================================================= }
{ fenetre principale de simulreflec                                             }
{ ============================================================================= }
{ 24.02.02 : FO : * nettoyage de cette unité en deportant les procedures de calcul }
{                   ainsi que les déclarations de variables                        }
{ 12.03.02 : FO : * il faut disposer d'un fichier par defaut poiur initialiser     }
{                   la grille multicouche                                          }
{                   MultiLayerSheetModel.xls et 'ParametersSheetModel.xls'         }
{ 04.04.02 : FO : * possibilité de calculer les différences entre deux jeux de courbes }
{                   experimentales et calculées                                        }
{ 15.04.02 : FO : * possibilité de fitter en mode non polarisé                         }
{ 16.04.02 : FO : * nouvelles procédures de sauvegarde et de lecture                   }
{                 DORENAVANT les fichiers auront l'en-tête suivant (non obligatoire!)  }
{                 les champs ne sont pas obligatoires                                  }
{                 on peut rajouter autant d elignes de commentaire a conditions de les faire précéder de # }
{ # Comment = Mon commentaire                                                          }
{ # Particles = neutrons OR xrays                                                      }
{ # Polarisation = non polarised OR polarised OR with spin-flip OR with SF high field  }
{ # AbscissesUnits = deg or nm-1                                                       }
{ # TimeOfFlight = true or false                                                       }
{ lors de la sauvagarde d'un fichier calculé, cet en-tête est automatiquement ajouté   }
{ 17.04.02 : FO : possiblité de fitter la normalisation                                }
{ 18.04.02 : FO : possibilité d'insérer, de copier et de coller, et détruire des lignes}
{ 19.04.02 : FO : copier et coller des data et des data calculées                      }
{ 11.05.02 : FO : mise a jour des para exp dans FormCreate                             }
{                 cochage "Y" fonctionne a nouveau                                     }
{                 affichage de la différence dans le panel fitting quand on calcule la différence NON POLARISE SLT ! }
{ 12.05.02 : FO : correction de la sauvegarde des paramètres de fit                    }
{                 faire attention aux noms des champs et aux unités                     }
{                 + ajout d'une décimale                                               }
{                 * ACHTUNG : les combo box doivent contenir des valeurs "conventionnée" }
{                   correction sur le weighting                                          }
{                 * possibilité de fitter en neutrons polarisés                          }
{                 * rétablissement du son                                                }
{ 27.05.02 : FO : * correction des affections directes des valeurs de pointeurs }
{ 30.05.02 : FO : * utilisation d'un fichier de fit par défaut unique au démarrage }
{                 * lecture du dernier fichier de fit sauvegardé au démarrage   }
{                   au lieu du dernier fichier fichier de fit ouvert            }
{                 * sauvegarde des spectres en lambda et en theta dans les fichiers de fit }
{ 17.06.02 : FO : * effacement "propres des feuilles de spectres de résolution  }
{                 * minimisationCrawling_P est différente de minimisationCrawling_P ! }
{                   + elle ne supporte pas les RX                               }
{ 19.06.02 : FO : * les deuilles de fichier de fit pour les lambda et les theta spectrum }
{                   doivent contenir au moins l'entete sinon plantage           }
{                   mais curieusement l'entete suffit !                         }
{                 * on peut maintenant fitter sans faire Calcul avant           }
{                   c'etait du a un probleme de mise a jour des data avant le fit }
{                 * désactiver la fonction de tri automatique lorsqu'on clique sur le header de la colonne }
{                   sort show = false                                           }
{ 21.06.02 : FO : * "correction" de la destruction des lignes                   }
{                   il faut faire : MultiLayerGrid.ClearRows(MultiLayerGrid.GetRealRow,1);  }
{                       ET          MultiLayerGrid.RemoveRows(MultiLayerGrid.GetRealRow,1); }
{                   +desactivation de MultiLayerGridAutoDeleteRow (correspondnant à la touche DEL ) }
{                   ne marche pas                                               }
{ 23.06.02 : FO : * remise en état des stability plots (+ corrections de noùmbreux bugs !! }
{ 26.06.02 : FO : * activation du range checking $R+ (a enlever pour gagner en vitesse }
{                 * reimplémentation des multicouches                           }
{                   avec en bonus la possibilité de fitter les ML               }
{                 * mise au clair de l'utilisation de "nbrLayers"               }
{                 * ajout d'une nouvelle fenetre de conversion pour faire l'équivalence }
{                   entre (delta,beta) et (lambda,density,f,f')                 }
{ *** Preparation pour la release 1.4 *** }
{ 15.07.02 : FO : * ajout des barres d'erreurs sur le plot des data             }
{                 * warning quand il y a des lignes blanches dans les data files}
{ 28.07.02:FO:* nouvelle procedure MiseAjourMultiLayerGrid(var MyML:TMultiLayer)}
{ 08.01.03:FO:* possibilité de faire le calcul de la difference en spin-flip    }
{             * touche DEL desactivée pour le tableau                           }
{             * masquage des colonnes non pertinentes en fonction des differentes options choisies }
{               Hide NE MARCHE PAS, a cause de la gestion des sauvegardes       }
{               On met la largeur des colonnes à zéro                           }
{ !!!!!!!!!!! * the polarised fitting is now working again !!!!!!               }
{             * possibility to fit spin-flip data again                         }
{             * possibilité de fitter le spin-flip only                         }
{ 10.01.03:FO:* possibilité de fitter/calculer avec la superposition de deux types de domaines     }
{               introduction d'une feuille "Multilayer2"                        }
{             * debut de la gestion des versions des fichiers de fit            }
{               en utilisant le champ "Version" des paramètres                  }
{               le "DefaultFitFile" est toujours à la norme dernière version    }
{               A noter : floats[y,x] n'aime pas les constantes                 }
{             * accélération du fit en spin-flip (facteur 2) en évitant les calculsl redondants }
{ 11.01.03:FO:* fix de la fuite de mémoire (freeIt manquant)                    }
{             * accélération du calcul SF d'un facteur 8                        }
{             * possibilité de faire des stability plots avec theta et phi      }
{ 14.01.03:FO:* implémentation des paramètres corrélés                          }
{               Nota: pour les para. corrélés il faut utiliser la boite 'step'  }
{               'Y' fit simple sans corr; 'A'- 'F' fit corrélé; '0' para numérique }
{               Bricolage : SetCorrParams faiut la diff entre n et x % 'rho_n' et 'rho_x' }
{                il faudrait passer la variable Experimental parameters         }
{ 17.01.03:FO:* les profils ont été implémentés de manière "propre"             }
{               des tests exhaustifs doivent etre réalisés                      }
{ 18.01.03:FO:* en principe il est possible d'utiliser les profils avec les polydomaines }
{               ca reste a tester sérieusement                                  }
{ 04.02.03:FO:* correction d'un bug d'arrondis dans le plot des profils SLD     }
{               mise à zero de l'abscisse substrat film                         }
{               tracé des profils en ERf des SLD                                }
{ 18.04.03:FO:* possiblité d'avoir des points manquants dans les fits et les plots }
{               les data expérimentales manquantes doivent contenir la valeur "0"  }
{ 18.08.03:FO:* implémentation des MDS                                          }
{               correction d'erreurs sur les test zYN etc                       }
{             * lecture/sauvegarde des MDSparams                                }
{ ============================================================================= }
{ A FAIRE                                                                       }
{ * si on met de la rugosité sur chaque couche d'un profil, cela n'a pas d'influence? }
{ * plus de 23 couches dans le profil -> le programme se plante                 }
{ * il serait judicieux de sauvegarder le nom du fichier de data auquel correspond le fit !!! }
{   à sauvegarder dans la feuille 'parameters'                                  }
{   c'est d'autant plus important pour les MDS fits                             }
{ * MDS : * calcul de la difference + plots ne focntionne pas avec les MDS      }
{ * changer le traitement de la convolution : suréchantillonner et calculer une seule courbe de réflectivité }
{ * probleme tres serieux : quand on calcule en polarise => oscillations bizarres au debut }
{   surtout si on utilise beaucoup de points                                    }
{ * par moment, on perd le controle sur les fiches lambda spectrum et theta spectrum }
{ * faut-il envisager de pouvoir ajouter des panels ML de manière dynamique     }
{   ca va etre sportif et probablement inutile pour le moment                   }
{ * association d'un jeu de data avec une feuille multilayer                    }
{ * possibilité de fitter simultanément plusieurs jeux de data (avec plusiers fichiers multilayers) }
{ * petit flou artistique lors du passage real-string dans la table MultiLayers }
{ * quand on fait stop après un fit, on perd le bon chi ???                     }
{ * à la fin d'un fit, on perd les valeurs précsies du chi                      }
{   c'est du aux arrondis dans la feuille Excel : même problème avec SiC        }
{ * sauvegarder le fitting range                                                }
{ ============================================================================= }
{ A NOTER                                                                       }
{ * le numéro de version du fichier de fit indique les feuilles présentes       }
{   il correspond au numéro de la release et indique quelles sont les feuilles  }
{   à lire                                                                      }
{ * "Difference" calcule la somme des CARRES                                    }
{ * Nota : la normalisation n'est pas appliquée dans le calcul de la réflectivité }
{   il faut l'appliquer séparément                                              }
{ * il existe trois niveaux de stockage des informations pour les paramètres experimentaux }
{       MyExpPara, MyParameters (grille), Les data dans la fenetre elle meme               }
{   lors des mises a jour des paramètres :                                                 }
{   au chargement d'un ficheir : charger le fichier de fit;                                }
{                   mettre a jour les data de la fenetre graphique ET la variable TExpPara }
{   avant un calcul : mettre a jour les para exp  partir de la fenetre graphique           }
{   sauvegarde d'un fichier de fit : mettre la grid à jour                                 }
{ ============================================================================= }
{ test des calculs de résolution                                                }
{ * PROBLEME 1 : la convolution complète (lambda - theta) donne un résultat sensiblement différent }
{   du cas ou on fait le calcul en gaussien (mais avec les memes spectres lambda et theta !!)      }
{ * quand on fait la convolution par une seule gaussiene (dans l'espace Qz c'est beaucoup plus mou }
{   quand on fait la convolution complète                                       }
{ * il ne faut pas utiliser des FWHM fractions trop grands sinon problème       }
{   on sous estime la resolution expérimentale                                  }
{ ============================================================================= }
{ ACHTUNG : pour les xrays, delta et beta dependent de lambda                   }
{           delta ~ lambda²   et beta ~ lambda²                                 }
{ ***************************************************************************** }
{ PNR - SDMS                                                                    }
{ lire les paramètres de sortie du fit                                          }
{ affichage du chi en "live"                                                    }


unit SimulReflecForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, SpecialFuncs,
  TeEngine, Series, ExtCtrls, TeeProcs, Chart, ndspl, math, Math387, MtxVec, MtxVecEdit, StdCtrls,
  EditReal, AxCtrls, OleCtrls, vcf1, Menus, Spin, PilotageGraph2D, optim, matrices, simOpt, clipBrd,
  ComCtrls, Grids, grilles, mathAux, Parser10, constants, probabilities,
  MPlayer, CheckLst, calculReflec, dataReflec, calculDiffus, calculGID, BaseGrid,
  AdvGrid, JvComponent, JvFormPlace, Editdata, JvMLButton, Buttons,
  JvBitBtn, JvLabel, JvCheckBox, JvTypedEdit, JvChrono, AdvCGrid,
  AdvGridExcel, JvSysComp;

type
  TSimulReflecWindow = class(TForm)
    OpenDialogDataFile: TOpenDialog;
    MainMenu: TMainMenu;
    OpenDialogLambdaSpectrum: TOpenDialog;
    SaveDialogCourbeReflec: TSaveDialog;
    Model1: TMenuItem;
    Insertnewlayer1: TMenuItem;
    OpenDialogFitFile: TOpenDialog;
    SaveDialogFitFile: TSaveDialog;
    OpenDialogThetaSpectrum: TOpenDialog;
    PageControl: TPageControl;
    TabSheetIO: TTabSheet;
    LambdaHeaderLength: TSpinEdit;
    ThetaHeaderLength: TSpinEdit;
    Label23: TLabel;
    FitFIleName: TEdit;
    DataFileName: TEdit;
    Label7: TLabel;
    Label11: TLabel;
    Label16: TLabel;
    WarningMessage: TLabel;
    Label10: TLabel;
    TabSheetExpPara: TTabSheet;
    TypePolarisation: TComboBox;
    Label6: TLabel;
    TabSheetFitting: TTabSheet;
    IterCrt: TLabel;
    FittingStatus: TLabel;
    TabSheetStability: TTabSheet;
    Label13: TLabel;
    Label14: TLabel;
    Label20: TLabel;
    StabilityPlotStatus: TLabel;
    DeuxDCheckBox: TCheckBox;
    Para2CheckBox: TCheckBox;
    Para1CheckBox: TCheckBox;
    para1combo: TComboBox;
    para1LayerNumber: TSpinEdit;
    Para2LayerNumber: TSpinEdit;
    Label18: TLabel;
    Para1min: TEditReal;
    Para2min: TEditReal;
    Label21: TLabel;
    Para1Max: TEditReal;
    Para2max: TEditReal;
    para1mesh: TSpinEdit;
    StabilityPlotButton: TButton;
    Para2mesh: TSpinEdit;
    para2combo: TComboBox;
    TabSheetML: TTabSheet;
    Label25: TLabel;
    NbrMLbox: TSpinEdit;
    TabSheetField: TTabSheet;
    AppliedFieldMag: TEditReal;
    Label30: TLabel;
    Label31: TLabel;
    Label32: TLabel;
    AppliedFieldTheta: TEditReal;
    AppliedFieldPhi: TEditReal;
    Shape3: TShape;
    ScrollBox1: TScrollBox;
    Image1: TImage;
    GroupBox4: TGroupBox;
    Label2: TLabel;
    ScanRangeMin: TEditReal;
    Label3: TLabel;
    ScanRangeStep: TEditReal;
    Label4: TLabel;
    ScanRangeMax: TEditReal;
    StopFittingButton: TButton;
    TabSheetCorrelations: TTabSheet;
    particlesChoice: TRadioGroup;
    TabSheetDiffuse: TTabSheet;
    Label5: TLabel;
    Label37: TLabel;
    Label43: TLabel;
    Abscisse: TRadioGroup;
    GroupBox5: TGroupBox;
    LabelD3: TLabel;
    LabelD4: TLabel;
    LabelD2: TLabel;
    LabelD1: TLabel;
    ScanType: TRadioGroup;
    ThetadiffMin: TEditReal;
    DeuxthetadiffMin: TEditReal;
    thetadiffstep: TEditReal;
    thetadiffmax: TEditReal;
    DiffStatus: TLabel;
    RangeDiff: TCheckBox;
    ProgressBar1: TProgressBar;
    TabSheetProfiles: TTabSheet;
    Memo3: TMemo;
    Memo4: TMemo;
    StopCalculDiff: TButton;
    CorEclairement: TCheckBox;
    intermediateRT: TCheckBox;
    intermediateRTlayerNr: TSpinEdit;
    FormalismRadioGroup: TRadioGroup;
    EvaluationTime: TEditReal;
    Label49: TLabel;
    Label56: TLabel;
    DeuxThetaDiffMax: TEditReal;
    DeuxThetaDiffStep: TEditReal;
    Label57: TLabel;
    Label47: TLabel;
    NormalisationDiffusBox: TEditReal;
    Deleteselectedlayer1: TMenuItem;
    Copyselectedlayer1: TMenuItem;
    Pasteselectedlayer1: TMenuItem;
    Label26: TLabel;
    Label27: TLabel;
    Label28: TLabel;
    TabSheetGratings: TTabSheet;
    Label29: TLabel;
    GratingPeriod: TEditReal;
    RadioGroupCorr: TRadioGroup;
    CorrelationFunction: TEdit;
    GroupBox8: TGroupBox;
    Label39: TLabel;
    Label40: TLabel;
    XsizBox: TEditReal;
    CheckBoxXsiz: TCheckBox;
    GroupBox11: TGroupBox;
    CheckBoxSmallAngles: TCheckBox;
    Label58: TLabel;
    GroupBox12: TGroupBox;
    xTestBorneSup: TEditReal;
    Label52: TLabel;
    Label59: TLabel;
    FFTvectorSizeBox: TComboBox;
    GaussOrderSpinEdit: TSpinEdit;
    Label38: TLabel;
    TabSheetSurfaceDiffraction: TTabSheet;
    Myinterest1: TMenuItem;
    Nonpolarisedspecularreflectivityreflectivity1: TMenuItem;
    Polarisedspecularreflectivity1: TMenuItem;
    Offspecularscattering1: TMenuItem;
    Everything1: TMenuItem;
    CheckBoxSound: TCheckBox;
    TabMultiFits: TTabSheet;
    RadioGroupAbscisseType: TRadioGroup;
    ParserCorrelations: TParser;
    calculatedDataComment: TEdit;
    Label36: TLabel;
    Label55: TLabel;
    DataFileComment: TEdit;
    PageControl1: TPageControl;
    ML1: TTabSheet;
    MultiLayerGrid: TAdvStringGrid;
    Parameters: TTabSheet;
    ParametersGrid: TAdvStringGrid;
    File2: TMenuItem;
    OpenFitFile2: TMenuItem;
    SaveFitFile2: TMenuItem;
    SaveMLasHTML1: TMenuItem;
    SaveParametersasHTML1: TMenuItem;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    SaveDialogHTML: TSaveDialog;
    Calculation2: TMenuItem;
    CalculateReflectivity1: TMenuItem;
    OpenDataFileMenu2: TMenuItem;
    N6: TMenuItem;
    N7: TMenuItem;
    Exit2: TMenuItem;
    SaveReflectivityCurveMenu: TMenuItem;
    N8: TMenuItem;
    CalculateReflectivityPhase2: TMenuItem;
    CalculateDifference2: TMenuItem;
    CalculateDiffuse2: TMenuItem;
    Fit3: TMenuItem;
    FitCrawlingMenu: TMenuItem;
    FitSimulatedAnnealing1: TMenuItem;
    FitGoldSearch1: TMenuItem;
    PasteDatafromClipboard1: TMenuItem;
    CopyDatatoClipboard1: TMenuItem;
    MediaPlayer1: TMediaPlayer;
    OpenLambdaSpectrum2: TMenuItem;
    OpenThetaSpectrum2: TMenuItem;
    N1: TMenuItem;
    LambdaSheet: TTabSheet;
    ThetaSheet: TTabSheet;
    LambdaSpectrumGrid: TAdvStringGrid;
    ThetaSpectrumGrid: TAdvStringGrid;
    Calc1: TMenuItem;
    JvFormPlace1: TJvFormPlace;
    Plotte1: TMenuItem;
    SLDProfiles1: TMenuItem;
    Probability1: TMenuItem;
    lambda1: TMenuItem;
    theta1: TMenuItem;
    QzIn1: TMenuItem;
    WaveFunction1: TMenuItem;
    TabSheetWaveFunction: TTabSheet;
    WFdimension: TRadioGroup;
    GroupBox2: TGroupBox;
    WFthetaMin: TEditReal;
    WFthetaStep: TEditReal;
    WFthetaMax: TEditReal;
    Label63: TLabel;
    Label64: TLabel;
    Label65: TLabel;
    GroupBox13: TGroupBox;
    DepthStep: TEditReal;
    Label66: TLabel;
    ProfilesGrid: TAdvStringGrid;
    JvMultilineButton1: TJvMultilineButton;
    FlagProfiling: TLabel;
    JvMultilineButton4: TJvMultilineButton;
    GroupBox14: TGroupBox;
    Label68: TLabel;
    LayerNr: TSpinEdit;
    CalculateIntermediateRT: TButton;
    ThetacGIDbox: TEditReal;
    CalculGID: TJvBitBtn;
    GroupBox15: TGroupBox;
    ThetainGIDmin: TEditReal;
    JvLabel1: TJvLabel;
    JvLabel9: TJvLabel;
    JvLabel10: TJvLabel;
    thetaInGIDStep: TEditReal;
    ThetaInGIDMax: TEditReal;
    JvLabel7: TJvLabel;
    exceptlayers: TEditReal;
    Label69: TLabel;
    LatticeParameterBox: TEditReal;
    CalcGIDPol: TButton;
    JvMultilineButton2: TJvMultilineButton;
    JvMultilineButton3: TJvMultilineButton;
    GroupBox3: TGroupBox;
    Label50: TLabel;
    NormBox: TEditReal;
    CheckBoxFitNorm: TCheckBox;
    NormFactorStepBox: TEditReal;
    TabSheet2: TTabSheet;
    GroupBox1: TGroupBox;
    dQzNbrBox: TSpinEdit;
    GroupBox16: TGroupBox;
    Label73: TLabel;
    Label61: TLabel;
    LambdaBox: TEditReal;
    Label75: TLabel;
    Label34: TLabel;
    dlambdaBox: TEditReal;
    GroupBox17: TGroupBox;
    Label70: TLabel;
    dlNbrBox: TSpinEdit;
    Label60: TLabel;
    ThetaBox: TEditReal;
    Label71: TLabel;
    Label74: TLabel;
    Label76: TLabel;
    dThetaBox: TEditReal;
    dTnbrBox: TSpinEdit;
    Label1: TLabel;
    LambdaMultiplier: TEditReal;
    ThetaMultiplier: TEditReal;
    Label77: TLabel;
    LambdaDistChoice: TRadioGroup;
    ThetaDistChoice: TRadioGroup;
    ConvolutionCalculationBox: TRadioGroup;
    QzMultiplier: TEditReal;
    Label72: TLabel;
    Label35: TLabel;
    dQzvstheta1: TMenuItem;
    QzFast1: TMenuItem;
    GroupBox18: TGroupBox;
    ToFCheckBox: TCheckBox;
    Label62: TLabel;
    angleBQ: TEditReal;
    polarisationBox: TEditReal;
    Label78: TLabel;
    FormFactorBox: TEditReal;
    Label79: TLabel;
    CalculGuntherButton: TButton;
    dQzInQzIn1: TMenuItem;
    ProgressGID: TProgressBar;
    StopGIDCalc: TButton;
    GroupBox19: TGroupBox;
    LayerIdxBox: TSpinEdit;
    ThetaC_LayerIndex: TSpinEdit;
    ResolutionGID: TJvCheckBox;
    GIDTermsGroup: TRadioGroup;
    Label80: TLabel;
    ThetaCLabel: TJvLabel;
    WFcalcStatus: TLabel;
    SaveMLasXML1: TMenuItem;
    InterfaceIdxBox: TSpinEdit;
    Label81: TLabel;
    RTvsdepth1: TMenuItem;
    GroupBox20: TGroupBox;
    FitAbsMin: TEditReal;
    FitAbsMax: TEditReal;
    Label82: TLabel;
    Label83: TLabel;
    GroupBox21: TGroupBox;
    Label84: TLabel;
    Label85: TLabel;
    Label86: TLabel;
    WFlambdaMin: TEditReal;
    WFlambdaStep: TEditReal;
    WFlambdaMax: TEditReal;
    CalculateWaveFunctionButton: TButton;
    STOPWaveFunctionButton: TButton;
    DataFittingOptionsBox: TRadioGroup;
    ML2: TTabSheet;
    MultiLayerGrid2: TAdvStringGrid;
    GroupBox23: TGroupBox;
    CopyML1intoML21: TMenuItem;
    FitCrawlingPolydomaines1: TMenuItem;
    PolydomainsMenu: TMenuItem;
    GroupBox24: TGroupBox;
    Label22: TLabel;
    Label87: TLabel;
    Fraction1Box: TEditReal;
    Fraction2box: TEditReal;
    PolyDomainsEnabledCheckBox: TCheckBox;
    GroupBox25: TGroupBox;
    Label8: TLabel;
    SpinEditNbrIter: TSpinEdit;
    Label15: TLabel;
    EcartBox: TEditReal;
    Label24: TLabel;
    PonderationTypeBox: TComboBox;
    StepBox: TEditReal;
    Label33: TLabel;
    Label51: TLabel;
    EcartBoxSmooth: TEditReal;
    Label67: TLabel;
    Label9: TLabel;
    NbrIterMaxBox: TSpinEdit;
    TolBox: TEditReal;
    Label19: TLabel;
    randomnessBox: TSpinEdit;
    Label88: TLabel;
    ElapsedTimeBox: TEditReal;
    Label89: TLabel;
    Label90: TLabel;
    Label91: TLabel;
    Label92: TLabel;
    dQzvsQz1: TMenuItem;
    dQzvsQzFast1: TMenuItem;
    GroupBox26: TGroupBox;
    JvLabel2: TJvLabel;
    ThetafMin: TEditReal;
    ThetafStep: TEditReal;
    JvLabel5: TJvLabel;
    JvLabel6: TJvLabel;
    ThetafMax: TEditReal;
    GIDthetaCbox: TListBox;
    SavingInProgress: TLabel;
    OpenMLasXML1: TMenuItem;
    CalculAlphaButton: TButton;
    WFthetaIn: TEditReal;
    Label93: TLabel;
    WFmemo: TMemo;
    MDSListBox: TListBox;
    GroupBox22: TGroupBox;
    Label17: TLabel;
    MDSpathBox: TEdit;
    GetDataButton: TButton;
    MDSSetBox: TSpinEdit;
    Label94: TLabel;
    ListBox1: TListBox;
    GroupBox28: TGroupBox;
    FitCrawlingMDSmenu: TMenuItem;
    MDSIndexBox: TSpinEdit;
    Label96: TLabel;
    TabSheetCombined: TTabSheet;
    Label95: TLabel;
    MultilayerGridIO: TAdvGridExcelIO;
    ParametersGridIO: TAdvGridExcelIO;
    MultiLayerGrid2IO: TAdvGridExcelIO;
    LambdaSpectrumGridIO: TAdvGridExcelIO;
    ThetaSpectrumGridIO: TAdvGridExcelIO;
    ProfilesGridIO: TAdvGridExcelIO;
    MDSparamsGridIO: TAdvGridExcelIO;
    MDSParamsGrid: TAdvStringGrid;
    CosPHI1: TMenuItem;
    PlotExperimentalCosPHIandSinPhi1: TMenuItem;
    ExperientalSpinAsymmetry1: TMenuItem;
    SpinAsymmDifferenceSA1: TMenuItem;
    CosPHIdifference1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;
    N4: TMenuItem;
    SinPHIDifference1: TMenuItem;
    TestButton: TButton;
    FontDialog1: TFontDialog;
    RxQ41: TMenuItem;
    GroupBox27: TGroupBox;
    Label97: TLabel;
    RoughnessFunction: TEdit;
    UseRoughnessFunction: TCheckBox;
    Label98: TLabel;
    MagnetizationFunction: TEdit;
    UseMagnetizationFunction: TCheckBox;
    Label99: TLabel;
    ThicknessFunction: TEdit;
    UseThicknessFunction: TCheckBox;
    PhiFunction: TEdit;
    Label100: TLabel;
    UsePhiFunction: TCheckBox;
    TabSheetSDMS: TTabSheet;
    Label101: TLabel;
    StartPNRbutton: TButton;
    LoadCalcButton: TButton;
    JvCreateProcess1: TJvCreateProcess;
    ExportParametersButton: TButton;
    LoadDataButton: TButton;
    BeamSizeBox: TGroupBox;
    Label53: TLabel;
    Label54: TLabel;
    VertSizeBox: TEditReal;
    GroupBox9: TGroupBox;
    Slit1caption: TLabel;
    Label103: TLabel;
    Slit1box: TEditReal;
    Slit2box: TEditReal;
    Label102: TLabel;
    SampleLengthBox: TEditReal;
    Label104: TLabel;
    Label105: TLabel;
    D1box: TEditReal;
    D2box: TEditReal;
    Label106: TLabel;
    Label107: TLabel;
    NptsBox: TSpinEdit;
    GroupBox29: TGroupBox;
    Label110: TLabel;
    Label111: TLabel;
    Label112: TLabel;
    Label113: TLabel;
    PolarizerEffBox: TEditReal;
    AnalyzerEffBox: TEditReal;
    Flipper1EffBox: TEditReal;
    Flipper2EffBox: TEditReal;
    BaseNameBox: TEdit;
    GroupBox10: TGroupBox;
    Label108: TLabel;
    Label109: TLabel;
    ScalingFactorBox: TEditReal;
    BackgroundBox: TEditReal;
    Label114: TLabel;
    GroupBox6: TGroupBox;
    Label42: TLabel;
    Label44: TLabel;
    Label45: TLabel;
    Label46: TLabel;
    Label48: TLabel;
    ComboBox1: TComboBox;
    SpinEdit1: TSpinEdit;
    EditReal1: TEditReal;
    EditReal2: TEditReal;
    SpinEdit2: TSpinEdit;
    EditReal3: TEditReal;
    Differentialevolution1: TMenuItem;
    ReplotButton: TButton;
    procedure FullSpectrumCheckBoxClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure TypePolarisationChange(Sender: TObject);
    procedure AboutButtonClick(Sender: TObject);
    procedure BugReportMenuClick(Sender: TObject);
    procedure SystemDescriptionModified(Sender: TObject);
    procedure PonderationTypeBoxExit(Sender: TObject);
    { GESTION DU SPECTRE EN LAMBDA }
{    procedure SetWLspectrum; }
    procedure SetWLspectrumButtonClick(Sender: TObject);
    procedure dlambdaBoxKeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);
    procedure dlambdaBoxExit(Sender: TObject);
    procedure dQzNbrBoxChange(Sender: TObject);
    { GESTION DU SPECTRE EN DTHETA }
{     procedure SetThetaSpectrum;}
    procedure dThetaBoxKeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);
    procedure dThetaBoxExit(Sender: TObject);
    procedure dTNbrBoxChange(Sender: TObject);
    procedure StopFittingButtonClick(Sender: TObject);
    procedure particlesChoiceClick(Sender: TObject);
{    procedure RangeAutoManClick(Sender: TObject);}
    procedure RangeDiffClick(Sender: TObject);
    procedure Memoxrays1Click(Sender: TObject);
    procedure RadioGroupCorrClick(Sender: TObject);
    procedure Nonpolarisedspecularreflectivityreflectivity1Click(
      Sender: TObject);
    procedure Polarisedspecularreflectivity1Click(Sender: TObject);
    procedure Offspecularscattering1Click(Sender: TObject);
    procedure Surfacediffraction1Click(Sender: TObject);
    procedure Gratings1Click(Sender: TObject);
    procedure Everything1Click(Sender: TObject);
    procedure TestFFT1Click(Sender: TObject);
    procedure OpenLastFitFileClick(Sender: TObject);
    procedure Exit1Click(Sender: TObject);
    procedure RadioGroupAbscisseTypeClick(Sender: TObject);
    procedure ToFCheckBoxClick(Sender: TObject);
    procedure UpdateVarExperimentalParameters(var MyParam:TExperimentalParameters);
    procedure OpenFitFile2Click(Sender: TObject);
    procedure SaveFitFile2Click(Sender: TObject);
    procedure SaveMLasHTML1Click(Sender: TObject);
    procedure SaveParametersasHTML1Click(Sender: TObject);
    procedure MultiLayerGridAutoDeleteRow(Sender: TObject; ARow: Integer);
    procedure MultiLayerGridAutoInsertCol(Sender: TObject; ACol: Integer);
    procedure Exit2Click(Sender: TObject);
    procedure OpenDataFileMenu2Click(Sender: TObject);
    procedure SaveReflectivityCurveMenuClick(Sender: TObject);
    procedure CalculateReflectivity1Click(Sender: TObject);
    procedure CalculateReflectivityPhase2Click(Sender: TObject);
    procedure FitCrawlingMenuClick(Sender: TObject);
    procedure CalculateDifference2Click(Sender: TObject);
    procedure ScanTypeClick(Sender: TObject);
    procedure Insertnewlayer1Click(Sender: TObject);
    procedure Deleteselectedlayer1Click(Sender: TObject);
    procedure Copyselectedlayer1Click(Sender: TObject);
    procedure Pasteselectedlayer1Click(Sender: TObject);
    procedure FitCrawlingRandomMenuClick(Sender: TObject);
    procedure CopyDatatoClipboard1Click(Sender: TObject);
    procedure PasteDatafromClipboard1Click(Sender: TObject);
    procedure OpenLambdaSpectrum2Click(Sender: TObject);
    procedure OpenThetaSpectrum2Click(Sender: TObject);
    procedure StabilityPlotButtonClick(Sender: TObject);
    procedure principalformPlotteprofile1Click(Sender: TObject);
    procedure PlotProfile(var MyML:TMultiLayer;var MyEP:TExperimentalParameters);
    procedure SLDProfiles1Click(Sender: TObject);
    procedure lambda1Click(Sender: TObject);
    procedure theta1Click(Sender: TObject);
    procedure WaveFunction1Click(Sender: TObject);
    procedure QzIn1Click(Sender: TObject);
    procedure JvMultilineButton2Click(Sender: TObject);
    procedure JvMultilineButton3Click(Sender: TObject);
    procedure JvMultilineButton1Click(Sender: TObject);
    procedure JvMultilineButton4Click(Sender: TObject);
    procedure CalculateIntermediateRTClick(Sender: TObject);
    procedure CalculGIDClick(Sender: TObject);
    procedure CalcGIDPolClick(Sender: TObject);
    procedure LambdaDistChoiceClick(Sender: TObject);
    procedure ThetaDistChoiceClick(Sender: TObject);
    procedure dQzvstheta1Click(Sender: TObject);
    procedure QzFast1Click(Sender: TObject);
    procedure dQzInQzIn1Click(Sender: TObject);
    procedure GenerateGIDSpectres;
    procedure CalculGuntherButtonClick(Sender: TObject);
    procedure angleBQKeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);
    procedure FormFactorBoxKeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);
    procedure StopGIDCalcClick(Sender: TObject);
    procedure polarisationBoxKeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);
    procedure UpdateGIDSetup;
    procedure layerIdxBoxChange(Sender: TObject);
    procedure ThetaCLabelClick(Sender: TObject);
    procedure ThetaC_LayerIndexChange(Sender: TObject);
    procedure SaveMLasXML1Click(Sender: TObject);
    procedure RTvsdepth1Click(Sender: TObject);
    procedure CalculateRTvsInterface(s:string;idx:integer;var MyML:TMultiLayer;var MyEP:TExperimentalParameters);
    procedure STOPWaveFunctionButtonClick(Sender: TObject);
    procedure TypePolarisationDragDrop(Sender, Source: TObject; X,Y: Integer);
    procedure TypePolarisationExit(Sender: TObject);
    procedure CopyML1intoML21Click(Sender: TObject);
    procedure FitCrawlingPolydomaines1Click(Sender: TObject);
    procedure PolydomainsMenuClick(Sender: TObject);
    procedure PolyDomainsEnabledCheckBoxClick(Sender: TObject);
    procedure ProfilesGridExit(Sender: TObject);
    procedure dQzvsQz1Click(Sender: TObject);
    procedure dQzvsQzFast1Click(Sender: TObject);
    procedure OpenMLasXML1Click(Sender: TObject);
    procedure CalculAlphaButtonClick(Sender: TObject);
    procedure GetDataButtonClick(Sender: TObject);
    procedure FitCrawlingMDSmenuClick(Sender: TObject);
    procedure MDSIndexBoxChange(Sender: TObject);
    procedure GroupBox28Click(Sender: TObject);
    procedure CosPHI1Click(Sender: TObject);
    procedure CalculdifferenceCosPhiSinPhi1Click(Sender: TObject);
    procedure PlotExperimentalCosPHIandSinPhi1Click(Sender: TObject);
    procedure ExperientalSpinAsymmetry1Click(Sender: TObject);
    procedure SpinAsymmDifferenceSA1Click(Sender: TObject);
    procedure CosPHIdifference;
    procedure CosPHIdifference1Click(Sender: TObject);
    procedure SinPHIDifference;
    procedure SinPHIDifference1Click(Sender: TObject);
    procedure TestButtonClick(Sender: TObject);
    procedure RxQ41Click(Sender: TObject);
    procedure StartPNRbuttonClick(Sender: TObject);
    procedure LoadCalcButtonClick(Sender: TObject);
    procedure ExportParametersButtonClick(Sender: TObject);
    procedure LoadDataButtonClick(Sender: TObject);
    procedure Differentialevolution1Click(Sender: TObject);
    procedure ReplotButtonClick(Sender: TObject);
  private
    function CheckPonderationCompatibility:boolean;
    { ================== }
    { Déclarations privées}
  public
    { Déclarations publiques}
    procedure SetLegendXYGraphPhi(s0,s1,s2,s3,s4:string);
    procedure XYGraphPhi_ReleaseUpdate(i:integer);
    Procedure PlayWave(s:string);
    procedure SetHeaders(MyEP:TExperimentalParameters;MyGrid:TAdvStringGrid);
    procedure UpdateSimulReflecWindowParameters(var MyParam:TExperimentalParameters);
    procedure SimulReflecFormClose;
    procedure MiseAjourMultiLayerGrid(var MyML:TMultiLayer;var MyGrid:TAdvStringGrid);
    procedure UpLoadMultiLayerGrid(var MyML:TMultiLayer;var MyGrid:TAdvStringGrid);
    procedure Transfer1DCurve(var x,z:Tvec;s:string);
    function  updateMDS_MLfromGrid(var MyMDS_ML:array of TMultiLayer;var MyEP:TexperimentalParameters):integer;
    procedure UPdateMDSfreeParams(var MyMDS_ML:array of TMultilayer;var MyEp:TexperimentalParameters);
    procedure UPdateMDSGridColHeaders(var MyMDS_ML:array of TMultilayer;var MyEp:TexperimentalParameters);
    procedure updateDisplayWhileFitting(var MyGrid:TAdvStringGrid;var MyMultiLayer:TMultiLayer;var MyExperimentalParameters:TExperimentalParameters;var chi:double);
    procedure RxQ4(R,Q,RQ4:Tvec);
    procedure PlotReflectivity(MyEP:TExperimentalParameters;MyDataCalc:TDataReflectivity);    
  end;


var
  SimulReflecWindow: TSimulReflecWindow;

var
  indexParam:integer;   { index du parametre en train d'etre fitté pour GoldSearch }

implementation

uses about, MainForm , Minimisation, WaveFunction{, EmailUnit}, FilesIO, DifferentialEvolution;

{$R *.DFM}

{ ========================================================================== }

Procedure TSimulReflecWindow.PlayWave(s:string);
begin
   if CheckBoxSound.checked=true
   then  With MediaPlayer1 do begin
         Filename := SourceDirectory+s+'.wav';
{         DeviceType := dtWaveAudio; }
         Open;
         Play;
         end;
end;

procedure TSimulReflecWindow.SetLegendXYGraphPhi(s0,s1,s2,s3,s4:string);
begin
   SRGraph1DForm.xyGraphPhi[SeriePhi1].clear;SRGraph1DForm.xyGraphPhi[SeriePhi1].holdupdates:=true;
   SRGraph1DForm.xyGraphPhi[SeriePhi2].clear;SRGraph1DForm.xyGraphPhi[SeriePhi2].holdupdates:=true;
   SRGraph1DForm.xyGraphPhi[SeriePhi3].clear;SRGraph1DForm.xyGraphPhi[SeriePhi3].holdupdates:=true;
   SRGraph1DForm.xyGraphPhi[SeriePhi4].clear;SRGraph1DForm.xyGraphPhi[SeriePhi4].holdupdates:=true;
   SRGraph1DForm.xyGraphPhi.Appearance.graphTitle:=s0;
   SRGraph1DForm.xyGraphPhi.Series[SeriePhi1].SeriesName:=s1;
   SRGraph1DForm.xyGraphPhi.Series[SeriePhi2].SeriesName:=s2;
   SRGraph1DForm.xyGraphPhi.Series[SeriePhi3].SeriesName:=s3;
   SRGraph1DForm.xyGraphPhi.Series[SeriePhi4].SeriesName:=s4;
end;

procedure TSimulReflecWindow.XYGraphPhi_ReleaseUpdate(i:integer);
begin
   SRGraph1DForm.xyGraphPhi[i].holdupdates:=false;
   SRGraph1DForm.xyGraphPhi[i].active:=true;
end;

{ ===========================================================}
{ procédures d'usage général                                 }
{ ===========================================================}

{ verification que les pondération sont non nulles et warning si une ponderation est nulle }
{ INPUT : none         }
{ OUTPUT : fenetre si il y a incompatibilté entre data exp et type de pondération    }
function TSimulReflecWindow.CheckPonderationCompatibility:boolean;
var r:boolean;
begin
    r:=true;
{    if ((PonderationType=2) or (PonderationType=3)) and (typePolarisation.text='non polarised')
    then begin
         for i:=0 to Rs.length-1 do
         begin
              if Rs[i]=0 then begin r:=false;MessageDlg('Variance is zero, you''ll have serious weighting problems. Load proper variance data, please!', mtInformation, [mbOk], 0);break; end;
         end;
         end;
    if ((PonderationType=2) or (PonderationType=3)) and (typePolarisation.text='polarised')
    then begin
         for i:=0 to RupS.length-1 do
         begin
              if (RupS[i]=0) or (RdoS[i]=0) then begin r:=false;MessageDlg('Variance is zero, you''ll have serious weighting problems. Load proper variance data, please!', mtInformation, [mbOk], 0);break; end;
         end;
         end;
    result:=r; }
    result:=true;
end;

{ initialisation du formulaire                         }
{ INPUT: none                                          }
{ OUTPUT: création de quelques vecteurs et matrices    }
{         initialisation du tableau avec trois couches }
procedure TSimulReflecWindow.FormCreate(Sender: TObject);
var nameF:textFile;
    pBuf:widestring;
    s:string;
    version:double;
begin
  { mise en place de la fenetre }
  windowState:=wsMinimized;
  Top:=420;Left:=0;Height:=340;Width:=1000;
  windowState:=wsMinimized;
{ affichage d'un minimum de tabs }
    TabSheetIO.TabVisible:=true;
    TabSheetExpPara.TabVisible:=true;
    TabSheetFitting.TabVisible:=true;
    TabSheetStability.TabVisible:=false;
    TabSheetML.TabVisible:=true;
    TabSheetField.TabVisible:=true;
    TabSheetDiffuse.TabVisible:=false;
    TabSheetProfiles.TabVisible:=false;
    TabSheetCorrelations.TabVisible:=false;
    TabSheetGratings.TabVisible:=false;
    TabSheetSurfaceDiffraction.TabVisible:=false;
    TabMultiFits.TabVisible:=false;
    TabSheetWaveFunction.TabVisible:=false;
    TabSheetCombined.TabVisible:=false;
    TabSheetSDMS.TabVisible:=false;
  { test du sépartuer décimal }
{  val('1.2',a,errorCode);
  if errorCode<>0 then MessageDlg('For a proper operation of the program, you MUST set the windows decimal symbol as dot "." and not comma "," ', mtInformation,[mbOk], 0); }
  { les commandes ci-dessus sont insensble à . et , }
  { Utilisation du tableau Excel }
  MultiLayerGrid.Floats[3,1]:=1.2;
  s:=MultiLayerGrid.Cells[3,1];
  if s='1,20' then MessageDlg('For a proper operation of the program, you MUST set the windows decimal symbol as dot "." and not comma "," ', mtInformation,[mbOk], 0);
  { répertoire de stockage du programme }
  SourceDirectory:=GetCurrentDir+'\';
  { creation des obejts de base }
  { lecture des derniers chemins et des derniers fichiers utilisés }
    AssignFile(NameF, SourceDirectory+'SimulReflec.par');
    Reset(NameF);
{    repeat  Readln(NameF, S);   until s[1]<>'#'; }
    readln(NameF,s);if DirectoryExists(s) then OpenDialogDataFile.initialDir:=s else OpenDialogDataFile.initialDir:=SourceDirectory;
    readln(NameF,s);if FileExists(s) then OpenDialogDataFile.fileName:=s else OpenDialogDataFile.fileName:='*.*';
    readln(NameF,s);if DirectoryExists(s) then SaveDialogCourbeReflec.initialDir:=s else SaveDialogCourbeReflec.initialDir:=SourceDirectory;
    readln(NameF,s);if DirectoryExists(s) then OpenDialogFitFile.initialDir:=s else OpenDialogFitFile.initialDir:=SourceDirectory;
    readln(NameF,s);if FileExists(s) then OpenDialogFitFile.fileName:=s else OpenDialogFitFile.fileName:='*.*';
    readln(NameF,s);if DirectoryExists(s) then SaveDialogFitFile.initialDir:=s else SaveDialogFitFile.initialDir:=SourceDirectory;
    readln(NameF,s);if FileExists(s) then SaveDialogFitFile.filename:=s else SaveDialogFitFile.filename:='*.*';
    readln(NameF,s);if DirectoryExists(s) then OpenDialogLambdaSpectrum.initialDir:=s else OpenDialogLambdaSpectrum.initialDir:=SourceDirectory;
    readln(NameF,s);if DirectoryExists(s) then OpenDialogThetaSpectrum.initialDir:=s else OpenDialogThetaSpectrum.initialDir:=SourceDirectory;
    closeFile(Namef);

{ ouverture du dernier fichier de fit }
     if FileExists(SaveDialogFitFile.FileName)
     then begin
          pBuf:=SaveDialogFitFile.FileName;
          { nouvelle méthode de sauvegarde }
          MultiLayerGridIO.XLSImport(pBuf,'MultiLayer');
          ParametersGridIO.XLSImport(pBuf,'Parameters');
          version:=ParametersGrid.floats[1,1];
          LambdaSpectrumGridIO.XLSImport(pbuf,'Lambda spectrum');
          ThetaSpectrumGridIO.XLSImport(pbuf,'Theta spectrum');
          ProfilesGridIO.XLSImport(pbuf,'Profiles');
          if version>=1.429  { problème si on met exactement 1.43 ?! }
          then MultiLayerGrid2IO.XLSImport(pBuf,'MultiLayer 2');
          if version>=1.489  { problème si on met exactement 1.49 ?! }
          then MDSparamsGridIO.XLSImport(pBuf,'MDSparams');
          if version<=1.499
          then begin MultiLayerGrid.Rowcount:=MultiLayerGrid.Rowcount+1;
               MultiLayerGrid2.Rowcount:=MultiLayerGrid.Rowcount+1;
               MDSparamsGrid.Rowcount:=MultiLayerGrid.Rowcount+1; end;

          FitFileName.text:=SaveDialogFitFile.FileName;
          end
     else begin { valeurs par défaut }
          { nouvelle méthode de lecture }
          pBuf:=sourceDirectory+'DefaultFitFile.xls';
          MultiLayerGridIO.XLSImport(pBuf,'MultiLayer');
          ParametersGridIO.XLSImport(pBuf,'Parameters');
          version:=ParametersGrid.floats[1,1];
          LambdaSpectrumGridIO.XLSImport(pbuf,'Lambda spectrum');
          ThetaSpectrumGridIO.XLSImport(pbuf,'Theta spectrum');
          ProfilesGridIO.XLSImport(pbuf,'Profiles');
          if version>=1.429  { problème si on met exactement 1.43 ?! }
          then MultiLayerGrid2IO.XLSImport(pBuf,'MultiLayer 2');
          if version>=1.489  { problème si on met exactement 1.49 ?! }
          then MDSparamsGridIO.XLSImport(pBuf,'MDSparams');
          if version<=1.499
          then begin MultiLayerGrid.Rowcount:=MultiLayerGrid.Rowcount+1;
               MultiLayerGrid2.Rowcount:=MultiLayerGrid.Rowcount+1;
               MDSparamsGrid.Rowcount:=MultiLayerGrid.Rowcount+1; end;
          end;
{ mise a jour des paramètres à partir de la grille }
  MyExperimentalParameters.UpdateVarExpParamFromGrid(ParametersGrid,LambdaSpectrumGrid,ThetaSpectrumGrid);
  UpdateSimulReflecWindowParameters(MyExperimentalParameters);
{ mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
{ mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

{ initialisation des grilles }
  SetHeaders(MyExperimentalParameters,MultiLayerGrid);
  SetHeaders(MyExperimentalParameters,MultiLayerGrid2);

{ ouverture du dernier fichier de data }
    if FileExists(OpenDialogDataFile.FileName)
    then begin
         MydataExp.ReadFromFile(MyExperimentalParameters,OpenDialogDataFile.FileName);
         SRGraph1Dform.PlotDataReflectivity(MyDataExp);
         UpdateSimulReflecWindowParameters(MyExperimentalParameters);
         DataFileName.text:=OpenDialogDataFile.FileName;
         end;
end;

procedure TSimulReflecWindow.FormClose(Sender: TObject;  var Action: TCloseAction);
var NameF:textFile;
begin
{ sauvegarde des répertoires en cours }
    AssignFile(NameF, SourceDirectory+'SimulReflec.par');{ Fichier sélectionné dans la boîte de dialogue }
    Rewrite(NameF);
    writeln(NameF,OpenDialogDataFile.initialDir);
    writeln(NameF,OpenDialogDataFile.fileName);
    writeln(NameF,SaveDialogCourbeReflec.initialDir);
    { pour le chemin OpenFitFile, on conserve le chemin du dernier fichier de fit sauvegardé }
    { writeln(NameF,OpenDialogFitFile.initialDir); } writeln(NameF,SaveDialogFitFile.initialDir);
    { writeln(NameF,OpenDialogFitFile.fileName); } writeln(NameF,SaveDialogFitFile.filename);
    writeln(NameF,SaveDialogFitFile.initialDir);
    writeln(NameF,SaveDialogFitFile.filename);
    writeln(NameF,OpenDialogLambdaSpectrum.initialDir);
    writeln(NameF,OpenDialogThetaSpectrum.initialDir);
    closeFile(Namef);
end;

procedure TSimulReflecWindow.SimulReflecFormClose;
var NameF:textFile;
begin
{ sauvegarde des répertoires en cours }
    AssignFile(NameF, SourceDirectory+'SimulReflec.par');{ Fichier sélectionné dans la boîte de dialogue }
    Rewrite(NameF);
    writeln(NameF,OpenDialogDataFile.initialDir);
    writeln(NameF,OpenDialogDataFile.fileName);
    writeln(NameF,SaveDialogCourbeReflec.initialDir);
    writeln(NameF,OpenDialogFitFile.initialDir);
    writeln(NameF,OpenDialogFitFile.fileName);
    writeln(NameF,SaveDialogFitFile.initialDir);
    writeln(NameF,SaveDialogFitFile.filename);
    writeln(NameF,OpenDialogLambdaSpectrum.initialDir);
    writeln(NameF,OpenDialogThetaSpectrum.initialDir);
    closeFile(Namef);
end;

{ ===========================================================}
{ GESTION GENERALE DU FORMULAIRE                             }
{ ===========================================================}

procedure TSimulReflecWindow.TypePolarisationChange(Sender: TObject);
begin
     { on efface toutes les courbes théoriques }
     SRGraph1Dform.xyGraph[SerieRcalcUP].clear;
     SRGraph1Dform.xyGraph[SerieRcalcDO].clear;
     SRGraph1Dform.xyGraph[SerieRcalcSF].clear;
     UpdateVarExperimentalParameters(MyExperimentalParameters);
     { on affiche que les partamètres pertinents }
     SetHeaders(MyExperimentalParameters,MultilayerGrid);
end;

procedure TSimulReflecWindow.FullSpectrumCheckBoxClick(Sender: TObject);
begin
{     If FullSpectrumCheckBox.checked=true
     then begin
          FullSpectrumCheckBox.checked:=false;
          lambdaBox.enabled:=true
          end
     else begin
          FullSpectrumCheckBox.checked:=true;
          lambdaBox.enabled:=false
          end }
    lambdaBox.enabled:=true
end;

procedure TSimulReflecWindow.AboutButtonClick(Sender: TObject);
begin
     AboutBox.visible:=true;
end;

procedure TSimulReflecWindow.BugReportMenuClick(Sender: TObject);
begin
{     SMTPForm.height:=304;SMTPForm.width:=435;
     SMTPForm.visible:=True; }
end;

procedure TSimulReflecWindow.SystemDescriptionModified(Sender: TObject);
begin
{  UpdateVCF1; } { peut poser des problemes lors de la lecture des fits }
end;

procedure TSimulReflecWindow.PonderationTypeBoxExit(Sender: TObject);
begin
{     RefreshParameters; }
end;

{ generation d'un spectre dlambda }
{ on fixe le nombre d epoints du spectre à 5 arbitrairement }
{ cette procédure n'a lieu d'etre que du point de vue de tests }
procedure TSimulReflecWindow.SetWLspectrumButtonClick(Sender: TObject);
begin { SetWLspectrum; }end;

procedure TSimulReflecWindow.dlambdaBoxKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin if key=13 then { SetWLspectrum }end;

procedure TSimulReflecWindow.dlambdaBoxExit(Sender: TObject);
begin { SetWLSpectrum } end;

procedure TSimulReflecWindow.dQzNbrBoxChange(Sender: TObject);
begin { SetWLSpectrum } end;

procedure TSimulReflecWindow.dThetaBoxKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin if key=13 then {SetThetaSpectrum;} end;

procedure TSimulReflecWindow.dThetaBoxExit(Sender: TObject);
begin { SetThetaSpectrum }end;

procedure TSimulReflecWindow.dTNbrBoxChange(Sender: TObject);
begin {SetThetaSpectrum } end;

procedure TSimulReflecWindow.StopFittingButtonClick(Sender: TObject);
begin
     StopFittingFlag:=true;
end;

procedure TSimulReflecWindow.particlesChoiceClick(Sender: TObject);
begin
   { en modes RX, on est en 'non polarisé' }
   if particlesChoice.itemIndex=1 then TypePolarisation.text:='non polarised';

   SRGraph1Dform.ClearCalc; { the previous calculations are erased }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { on affiche que les partamètres pertinents }
   SetHeaders(MyExperimentalParameters,MultilayerGrid);
end;


{ =============================================================================}
{ =============================================================================}
{ Calcul tenant compte de la rugosite en DWBA dans une multicouche             }
{ =============================================================================}
{ =============================================================================}


{ ============================================================================}
{choix du type de scan, soit a 2-theta fixe, soit a theta incident fixe       }
{ ============================================================================}
procedure TSimulReflecWindow.ScanTypeClick(Sender: TObject);
begin
{choix du type de scan pour le calcul du Diffus}
if ScanType.Items[ScanType.Itemindex] = 'fixed 2T' then
begin
rangediff.checked:=true;
rangediff.caption:='AutoRange';
Abscisse.itemindex:=0;
Abscisse.Items[0]:= '(Thetai-Thetaf)/2';
Abscisse.Items[1]:= 'Qx  (1/Å)';
Abscisse.Items[2]:= 'Thetai';
thetadiffmax.value:=deuxthetadiffMax.value-thetadiffstep.value;
thetadiffmin.value:=thetadiffStep.value;
{ on desactive les bouttons 2T inutiles }
deuxThetaDiffMax.enabled:=true;deuxThetaDiffMin.enabled:=false;deuxThetaDiffStep.enabled:=false;
ThetaDiffMax.enabled:=true;ThetaDiffMin.enabled:=true;ThetaDiffStep.enabled:=true;
end;
if ScanType.Items[ScanType.Itemindex] = 'fixed T' then
begin
rangediff.checked:=true;
rangediff.caption:='AutoRange';
Abscisse.itemindex:=0;
Abscisse.Items[0]:= 'Deux Theta';
Abscisse.Items[1]:= 'Qx  (1/Å)';
Abscisse.Items[2]:= '';
deuxthetadiffmax.value:=2*thetadiffMax.value;
deuxthetadiffmin.value:=deuxthetadiffStep.value;
deuxThetaDiffMax.enabled:=true;deuxThetaDiffMin.enabled:=true;deuxThetaDiffStep.enabled:=true;
ThetaDiffMax.enabled:=true;ThetaDiffMin.enabled:=false;ThetaDiffStep.enabled:=false;
end;
if ScanType.Items[ScanType.Itemindex] = 'longit.' then { scans longitudinaux }
begin
rangediff.checked:=true;
rangediff.caption:='AutoRange';
Abscisse.itemindex:=0;
Abscisse.Items[0]:= 'Theta';
Abscisse.Items[1]:= 'Deux Theta';
Abscisse.Items[2]:= '';
deuxThetaDiffMax.enabled:=true;deuxThetaDiffMin.enabled:=true;deuxThetaDiffStep.enabled:=true;
ThetaDiffMax.enabled:=false;ThetaDiffMin.enabled:=false;ThetaDiffStep.enabled:=true;
end;
if ScanType.Items[ScanType.Itemindex] = '2D' then
begin
rangediff.checked:=false;
rangediff.caption:='ManualRange';
Abscisse.itemindex:=0;
Abscisse.Items[0]:= 'Thetaf';
Abscisse.Items[1]:= 'Qx  (1/Å)';
Abscisse.Items[2]:= '';
thetadiffmax.value:=deuxthetadiffMax.value-thetaDiffStep.value;
thetadiffmin.value:=thetadiffStep.value;
{ on desactive 2t et on imposera 0 < 2T < Theta in + theta f }
deuxThetaDiffMax.enabled:=false;deuxThetaDiffMin.enabled:=false;deuxThetaDiffStep.enabled:=false;
ThetaDiffMax.enabled:=true;ThetaDiffMin.enabled:=true;ThetaDiffStep.enabled:=true;
end;

end;

procedure TSimulReflecWindow.RangeDiffClick(Sender: TObject);
begin
if rangediff.checked=false then rangediff.caption:='ManualRange';
if rangediff.checked=true then
begin
    rangediff.caption:='AutoRange';
    if ScanType.Items[ScanType.Itemindex] = 'fixed 2T' then
    begin
    thetadiffmax.value:=deuxthetadiffMin.value-thetadiffstep.value;
    thetadiffmin.value:=thetadiffstep.value;
    end;
    if ScanType.Items[ScanType.Itemindex] = 'fixed T' then
    begin
    thetadiffmax.value:=0.5*deuxthetadiffMin.value;
    thetadiffmin.value:=thetadiffstep.value;
    end;
end;
end;

procedure TSimulReflecWindow.Memoxrays1Click(Sender: TObject);
begin
   Application.HelpFile := SourceDirectory+'help\SimulReflec.HLP';
   Application.HelpCommand(HELP_FINDER, 0);
end;

procedure TSimulReflecWindow.RadioGroupCorrClick(Sender: TObject);
begin
     CheckBoxSmallAngles.checked:=true;
end;

procedure TSimulReflecWindow.Nonpolarisedspecularreflectivityreflectivity1Click(
  Sender: TObject);
begin
    TabSheetIO.TabVisible:=true;
    TabSheetExpPara.TabVisible:=true;
    TabSheetFitting.TabVisible:=true;
    TabSheetStability.TabVisible:=false;
    TabSheetML.TabVisible:=true;
    TabSheetField.TabVisible:=false;
    TabSheetDiffuse.TabVisible:=false;
    TabSheetProfiles.TabVisible:=false;
    TabSheetCorrelations.TabVisible:=false;
    TabSheetGratings.TabVisible:=false;
    TabSheetSurfaceDiffraction.TabVisible:=false;
    TabMultiFits.TabVisible:=false;
    TabSheetWaveFunction.TabVisible:=false;
    TabSheetCombined.TabVisible:=false;
    TabSheetSDMS.TabVisible:=false;
end;

procedure TSimulReflecWindow.Polarisedspecularreflectivity1Click(
  Sender: TObject);
begin
    TabSheetIO.TabVisible:=true;
    TabSheetExpPara.TabVisible:=true;
    TabSheetFitting.TabVisible:=true;
    TabSheetStability.TabVisible:=false;
    TabSheetML.TabVisible:=true;
    TabSheetField.TabVisible:=true;
    TabSheetDiffuse.TabVisible:=false;
    TabSheetProfiles.TabVisible:=false;
    TabSheetCorrelations.TabVisible:=false;
    TabSheetGratings.TabVisible:=false;
    TabSheetSurfaceDiffraction.TabVisible:=false;
    TabMultiFits.TabVisible:=false;
    TabSheetWaveFunction.TabVisible:=false;
    TabSheetCombined.TabVisible:=false;
    TabSheetSDMS.TabVisible:=false;
end;

procedure TSimulReflecWindow.Offspecularscattering1Click(Sender: TObject);
begin
    TabSheetIO.TabVisible:=true;
    TabSheetExpPara.TabVisible:=true;
    TabSheetFitting.TabVisible:=false;
    TabSheetStability.TabVisible:=false;
    TabSheetML.TabVisible:=true;
    TabSheetField.TabVisible:=true;
    TabSheetDiffuse.TabVisible:=true;
    TabSheetProfiles.TabVisible:=false;
    TabSheetCorrelations.TabVisible:=true;
    TabSheetGratings.TabVisible:=false;
    TabSheetSurfaceDiffraction.TabVisible:=false;
    TabMultiFits.TabVisible:=false;
    TabSheetWaveFunction.TabVisible:=false;
    TabSheetCombined.TabVisible:=false;
    TabSheetSDMS.TabVisible:=true;
end;

procedure TSimulReflecWindow.Surfacediffraction1Click(Sender: TObject);
begin
    TabSheetIO.TabVisible:=true;
    TabSheetExpPara.TabVisible:=true;
    TabSheetFitting.TabVisible:=false;
    TabSheetStability.TabVisible:=false;
    TabSheetML.TabVisible:=true;
    TabSheetField.TabVisible:=true;
    TabSheetDiffuse.TabVisible:=false;
    TabSheetProfiles.TabVisible:=false;
    TabSheetCorrelations.TabVisible:=true;
    TabSheetGratings.TabVisible:=false;
    TabSheetSurfaceDiffraction.TabVisible:=true;
    TabMultiFits.TabVisible:=false;
    TabSheetWaveFunction.TabVisible:=false;
    TabSheetCombined.TabVisible:=false;
    TabSheetSDMS.TabVisible:=false;
end;

procedure TSimulReflecWindow.Gratings1Click(Sender: TObject);
begin
    TabSheetIO.TabVisible:=true;
    TabSheetExpPara.TabVisible:=true;
    TabSheetFitting.TabVisible:=false;
    TabSheetStability.TabVisible:=false;
    TabSheetML.TabVisible:=true;
    TabSheetField.TabVisible:=true;
    TabSheetDiffuse.TabVisible:=false;
    TabSheetProfiles.TabVisible:=false;
    TabSheetCorrelations.TabVisible:=true;
    TabSheetGratings.TabVisible:=true;
    TabSheetSurfaceDiffraction.TabVisible:=false;
    TabMultiFits.TabVisible:=false;
    TabSheetWaveFunction.TabVisible:=false;
    TabSheetCombined.TabVisible:=false;
    TabSheetSDMS.TabVisible:=false;
end;

procedure TSimulReflecWindow.Everything1Click(Sender: TObject);
begin
    TabSheetIO.TabVisible:=true;
    TabSheetExpPara.TabVisible:=true;
    TabSheetFitting.TabVisible:=true;
    TabSheetStability.TabVisible:=true;
    TabSheetML.TabVisible:=true;
    TabSheetField.TabVisible:=true;
    TabSheetDiffuse.TabVisible:=true;
    TabSheetProfiles.TabVisible:=true;
    TabSheetCorrelations.TabVisible:=true;
    TabSheetGratings.TabVisible:=true;
    TabSheetSurfaceDiffraction.TabVisible:=true;
    TabMultiFits.TabVisible:=true;
    TabSheetWaveFunction.TabVisible:=true;
    TabSheetCombined.TabVisible:=true;
    TabSheetSDMS.TabVisible:=true;
end;

{ procedure de test de calcul des FFT avec MtxVec     }
{ pour le calcul des FT des fonctions de corrélation  }
{ power ne s'applique pas pour x=0 ? ets-ce normal ?  }
procedure TSimulReflecWindow.TestFFT1Click(Sender: TObject);
var i,fftLength:integer;
    C,Xvect,Xi,Cq,CqR,CqI,Qxi:Tvec;
    x,xstep,sigval,xsival,hval:double;
    critereIntegral,xlimit:double;
begin
     critereIntegral:=xTestBorneSup.value;
     sigval:=1e-9;xsival:=10000e-9;hval:=1;
     xlimit:=xsival*Power(-ln(critereIntegral),1/(2*hval));
     fftLength:=StrToInt(FFTVectorSizebox.text);
     createIt(C,Xvect,Xi,Qxi);createIt(Cq,CqR,CqI);
     C.Size(fftLength,false);Cq.Size(fftLength,false);
     Xvect.Size(fftLength,false);Xi.Size(fftLength,false);Qxi.Size(round(fftLength/2),false);
{ creation du vecteur a FT a partir de la fonction analytique C(X) }
     xstep:=xlimit/fftLength;x:=xstep;
     for i:=0 to fftLength-1 do
     begin
          Xvect[i]:=x;Xi[i]:=i;
          C[i]:=sigval*sigval*exp(-Power(x/xsival,2*hval));
          x:=x+xstep;
     end;
{ tracé de la fonction de corrélation }
{     Graph2Dform.TransferCurve(Xvect,C,4); }
     SRGraph1DForm.TransferCurve(Xi,C,4);
     Cq.fft(C);CqR.Realpart(Cq);CqI.ImagPart(Cq);
     for i:=0 to round(fftLength/2-1) do Qxi[i]:=i;
     SRGraph1DForm.TransferCurve(Qxi,CqR,5);
     SRGraph1DForm.TransferCurve(Qxi,CqI,6);
     freeit(C,Cq,Xvect,Xi);freeit(Qxi);
end;

procedure TSimulReflecWindow.OpenLastFitFileClick(Sender: TObject);
begin
     if FileExists(OpenDialogFitFile.FileName) then {openFitFile; }
end;

procedure TSimulReflecWindow.Exit1Click(Sender: TObject);
begin
   close;
end;

procedure TSimulReflecWindow.RadioGroupAbscisseTypeClick(Sender: TObject);
var i:integer;
begin
   case RadioGroupAbscissetype.itemIndex of
    0:begin
      SRGraph1DForm.xygraph.XAxis.title:='Theta (degrees)';
      with MyDataExp do
      begin
         AbscissesUnits:='deg';
         for i:=0 to Angles.length-1 do Abscisses[i]:=angles[i]*180/pi;
      end;
      end;
    1:begin
      SRGraph1DForm.xygraph.XAxis.title:='Qz (nm-1)';
      with MyDataExp do
      begin
         AbscissesUnits:='nm-1';
         for i:=0 to Qz.length-1 do Abscisses[i]:=Qz[i]*1e-9;
      end;
      end;
   end;
   { replot avec les nouvelles abscisses }
   SRGraph1Dform.ClearCalc;
   SRGraph1Dform.PlotDataReflectivity(MyDataExp);
end;

procedure TSimulReflecWindow.ToFCheckBoxClick(Sender: TObject);
begin
     TofCheckBox.update;
     if TofCheckBox.checked=false
     then begin lambdaBox.enabled:=true;lambdaBox.update;
                thetaBox.enabled:=false;thetaBox.update;
                if ConvolutionCalculationBox.itemIndex=0 then ConvolutionCalculationBox.itemIndex:=1;
                WFthetaMin.enabled:=true;WFthetaMin.update;
                WFthetaStep.enabled:=true;WFthetaStep.update;
                WFthetaMax.enabled:=true;WFthetaMax.update;
                WFlambdaMin.enabled:=false;WFlambdaMin.update;
                WFlambdaStep.enabled:=false;WFlambdaStep.update;
                WFlambdaMax.enabled:=false;WFlambdaMax.update;
                {GroupBox2 Thetain Box dans WaveFunction, GroupBox21 Lambda Box dans WaveFunction}
                GroupBox2.ShowHint:=false;
                GroupBox21.ShowHint:=true;
                end
     else begin lambdaBox.enabled:=false;lambdaBox.update;
                thetaBox.enabled:=true;thetaBox.update;
                WFthetaMin.enabled:=false;WFthetaMin.update;
                WFthetaStep.enabled:=false;WFthetaStep.update;
                WFthetaMax.enabled:=false;WFthetaMax.update;
                WFlambdaMin.enabled:=true;WFlambdaMin.update;
                WFlambdaStep.enabled:=true;WFlambdaMin.update;
                WFlambdaMax.enabled:=true;WFlambdaMax.update;
                {GroupBox2 Thetain Box dans WaveFunction, GroupBox21 Lambda Box dans WaveFunction}
                GroupBox2.ShowHint:=true;
                GroupBox21.ShowHint:=false;
                end;
end;

{ ============================================================================= }
{ ============================================================================= }
{ nouvelles procedures utilisant les nouvelles variables                        }
{ ============================================================================= }
{ ============================================================================= }

{ mise a jour d'une variable TExperimentalParameters a partir des informations  }
{ de la fenetre SimulReflecWindow                                               }
procedure TSimulReflecWindow.UpdateVarExperimentalParameters(var MyParam:TExperimentalParameters);
begin
    MyParam.calculatedDataComment:=calculatedDataComment.text;
    if RadioGroupAbscisseType.itemindex=0 then MyParam.AbscissesUnits:='deg' else MyParam.AbscissesUnits:='nm-1';
    { experimental parameters }
    MyParam.PolarisationType:=TypePolarisation.text;
    MyParam.Tof:=ToFCheckBox.checked;
    MyParam.lambda:=lambdaBox.value*1e-9;MyParam.dlambda:=dlambdabox.value*1e-9;
    MyParam.theta:=thetaBox.value*pi/180;MyParam.dtheta:=dthetaBox.value*pi/180;
    MyParam.dLambdaNbr:=dlNbrBox.value;MyParam.dThetaNbr:=dtNbrBox.value;
    MyParam.lambdaMult:=lambdaMultiplier.value;MyParam.thetaMult:=thetaMultiplier.value;MyParam.QzMult:=QzMultiplier.value;
    MyParam.dQzNbr:=dQzNbrBox.value;
{    MyParam.FWHMFraction:=FWHMFraction.value; }
    if (lambdaDistChoice.itemIndex=0) and (thetaDistChoice.itemIndex=1)
    then MyParam.convolution:='full theta';
    if (lambdaDistChoice.itemIndex=1) and (thetaDistChoice.itemIndex=0)
    then MyParam.convolution:='full lambda';
    if (lambdaDistChoice.itemIndex=1) and (thetaDistChoice.itemIndex=1)
    then MyParam.convolution:='full theta & lambda';
    if (lambdaDistChoice.itemIndex=0) and (thetaDistChoice.itemIndex=0)
    then MyParam.convolution:='gaussian';
    if COnvolutionCalculationBox.itemIndex=0 then MyParam.ConvolutionCalculation:='full';
    if COnvolutionCalculationBox.itemIndex=1 then MyParam.ConvolutionCalculation:='QzGaussian';
    if COnvolutionCalculationBox.itemIndex=2 then MyParam.ConvolutionCalculation:='QzFast';
    { generation ou lecture des spectres de resolution }
    MyParam.updateDistributions(LambdaSpectrumGrid,ThetaSpectrumGrid);
    if ParticlesChoice.itemindex=0 then MyParam.particles:='neutrons' else MyParam.particles:='xrays';
    MyParam.VertSize:=vertSizeBox.value;
    MyParam.ScanRangeMin:=ScanRangeMin.value;
    MyParam.ScanRangeStep:=ScanRangeStep.value;
    MyParam.ScanRangeMax:=ScanRangeMax.value;
    { FIELD }
    MyParam.FieldMag:=AppliedFieldMag.value*0.001; { passage de mT en T }
    MyParam.FieldTheta:=AppliedFieldTheta.value*pi/180; { passage de ° en rad }
    MyParam.FieldPhi:=AppliedFieldPhi.value*pi/180;
    { MULTILAYERS }
    MyParam.nbrML:=NbrMLBox.value;
    MyParam.thicknessFunction:=thicknessFunction.Text;
    MyParam.UseThicknessFunction:=UseThicknessFunction.checked;
    MyParam.roughnessFunction:=roughnessFunction.Text;
    MyParam.UseRoughnessFunction:=UseRoughnessFunction.checked;
    MyParam.MagnetizationFunction:=MagnetizationFunction.Text;
    MyParam.UseMagnetizationFunction:=UseMagnetizationFunction.checked;
    MyParam.PhiFunction:=PhiFunction.Text;
    MyParam.UsePhiFunction:=UsePhiFunction.checked;
    { FITTING PARAMETERS }
    MyParam.NormalisationFactor:=NormBox.value;
    MyParam.NormalisationFactorStep:=NormFactorStepBox.value;
    MyParam.FitNormalisation:=CheckBoxFitNorm.checked;
    MyParam.NbrIterations:=SpinEditNbrIter.value;MyParam.randomness:=randomnessBox.value;
    MyParam.PonderationType:=PonderationTypeBox.text;
    MyParam.FitStep:=StepBox.value;
    { DIFFUSE }
    case scanType.itemIndex of
    1:MyParam.scanType:='fixed 2T';
    2:MyParam.scanType:='fixed T';
    3:MyParam.scanType:='fixed longit.';
    4:MyParam.scanType:='2D';
    end;
    MyParam.ThetaDiffMin:=ThetaDiffMin.value;MyParam.ThetaDiffMax:=ThetaDiffMax.value;MyParam.ThetaDiffStep:=ThetaDiffStep.value;
    MyParam.DeuxThetaDiffMin:=DeuxThetaDiffMin.value;MyParam.DeuxThetaDiffMax:=DeuxThetaDiffMax.value;MyParam.DeuxThetaDiffStep:=DeuxThetaDiffStep.value;
    MyParam.AutoRangeDiff:=RangeDiff.checked;
{    AbscisseDiffType,FormalismDiffType:string; }
end;

{ mise a jour des paramètres de la fenetre SimulReflecWindow                    }
{ a partir d'une variable TExperimentalParameters                               }
procedure TSimulReflecWindow.UpdateSimulReflecWindowParameters(var MyParam:TExperimentalParameters);
begin
    calculatedDataComment.text:=MyParam.calculatedDataComment;
    DataFileComment.text:=MyParam.name;
    if MyParam.AbscissesUnits='deg' then RadioGroupAbscisseType.itemindex:=0 else RadioGroupAbscisseType.itemindex:=1;
    { experimental parameters }
    TypePolarisation.text:=MyParam.PolarisationType;
    ToFCheckBox.checked:=MyParam.Tof;
    lambdaBox.value:=MyParam.lambda/1e-9;dlambdabox.value:=MyParam.dlambda/1e-9;
    thetaBox.value:=MyParam.theta*180/pi;dthetaBox.value:=MyParam.dtheta*180/pi;
    dlNbrBox.value:=MyParam.dLambdaNbr;dtNbrBox.value:=MyParam.dThetaNbr;dQzNbrBox.value:=MyParam.dQzNbr;
    lambdaMultiplier.value:=MyParam.lambdaMult;thetaMultiplier.value:=MyParam.thetaMult;QzMultiplier.value:=MyParam.QzMult;
    { check boc de convolution }
    if MyParam.convolution='full theta'
    then begin lambdaDistChoice.itemIndex:=0;thetaDistChoice.itemIndex:=1 end;
    if MyParam.convolution='full lambda'
    then begin lambdaDistChoice.itemIndex:=1;thetaDistChoice.itemIndex:=0 end;
    if MyParam.convolution='full theta & lambda'
    then begin lambdaDistChoice.itemIndex:=1;thetaDistChoice.itemIndex:=1 end;
    if MyParam.convolution='gaussian'
    then begin lambdaDistChoice.itemIndex:=0;thetaDistChoice.itemIndex:=0 end;
    if MyParam.ConvolutionCalculation='full' then COnvolutionCalculationBox.itemIndex:=0;
    if MyParam.ConvolutionCalculation='QzGaussian' then COnvolutionCalculationBox.itemIndex:=1;
    if MyParam.ConvolutionCalculation='QzFast' then COnvolutionCalculationBox.itemIndex:=2;
{    FWHMFraction.value:=MyParam.FWHMFraction; }
    vertSizeBox.value:=MyParam.VertSize;
    ScanRangeMin.value:=MyParam.ScanRangeMin;
    ScanRangeStep.value:=MyParam.ScanRangeStep;
    ScanRangeMax.value:=MyParam.ScanRangeMax;
    { FIELD }
    AppliedFieldMag.value:=MyParam.FieldMag*1000;        { on repasse en unités agréables }
    AppliedFieldTheta.value:=MyParam.FieldTheta*180/pi;
    AppliedFieldPhi.value:=MyParam.FieldPhi*180/pi;
    { MULTILAYERS }
    NbrMLBox.value:=MyParam.nbrML;
    thicknessFunction.Text:=MyParam.thicknessFunction;
    UseThicknessFunction.checked:=MyParam.UseThicknessFunction;
    roughnessFunction.Text:=MyParam.roughnessFunction;
    UseRoughnessFunction.checked:=MyParam.UseRoughnessFunction;
    MagnetizationFunction.Text:=MyParam.MagnetizationFunction;
    UseMagnetizationFunction.checked:=MyParam.UseMagnetizationFunction;
    PhiFunction.Text:=MyParam.PhiFunction;
    UsePhiFunction.checked:=MyParam.UsePhiFunction;
    { FITTING PARAMETERS }
    NormBox.value:=MyParam.NormalisationFactor;
    NormFactorStepBox.value:=MyParam.NormalisationFactorStep;
    CheckBoxFitNorm.checked:=MyParam.FitNormalisation;
    SpinEditNbrIter.value:=MyParam.NbrIterations;randomnessBox.value:=MyParam.randomness;
    PonderationTypeBox.text:=MyParam.PonderationType;
    StepBox.value:=MyParam.FitStep;
    { DIFFUSE }
    if MyParam.scanType='fixed 2T' then scanType.itemIndex:=1;
    if MyParam.scanType='fixed T' then scanType.itemIndex:=2;
    if MyParam.scanType='fixed longit.' then scanType.itemIndex:=3;
    if MyParam.scanType='2D' then scanType.itemIndex:=4;
    ThetaDiffMin.value:=MyParam.ThetaDiffMin;ThetaDiffMax.value:=MyParam.ThetaDiffMax;ThetaDiffStep.value:=MyParam.ThetaDiffStep;
    DeuxThetaDiffMin.value:=MyParam.DeuxThetaDiffMin;DeuxThetaDiffMax.value:=MyParam.DeuxThetaDiffMax;DeuxThetaDiffStep.value:=MyParam.DeuxThetaDiffStep;
    RangeDiff.checked:=MyParam.AutoRangeDiff;

    { on affiche que les partamètres pertinents }
     if TypePolarisation.text='non polarised'
     then with MultiLayerGrid do
                begin colWidths[colM]:=0;colWidths[colMYN]:=0;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=0;colWidths[colPhiYN]:=0;
                end;
     if TypePolarisation.text='polarised'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=0;colWidths[colPhiYN]:=0;
                end;
     if TypePolarisation.text='with spin-flip'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=colUnit*5;colWidths[colPhiYN]:=colUnit*4;
                end;
     if TypePolarisation.text='with SF high field'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=colUnit*5;colWidths[colThetaYN]:=colUnit*4;
                      colWidths[colPhi]:=colUnit*5;colWidths[colPhiYN]:=colUnit*4;
                end;
    { this set of instructions is at the end because ParticlesChoice.itemindex:=0 calls an event }
    { which messes up MyExperimentalParameters }
    if MyParam.particles='neutrons'
    then begin ParticlesChoice.itemindex:=0;setHeaders(MyParam,MultiLayerGrid);SetHeaders(MyParam,MultiLayerGrid2); end
    else begin ParticlesChoice.itemindex:=1;setHeaders(MyParam,MultiLayerGrid);SetHeaders(MyParam,MultiLayerGrid2); end;
end;


{ ============================================================================= }
{ nouveaux menus }
{ ============================================================================= }
procedure TSimulReflecWindow.OpenFitFile2Click(Sender: TObject);
var pBuf:widestring;
    CurrentDir:string;
    version:double;
begin
  if OpenDialogFitFile.Execute then  { Affichage de la boîte de dialogue d'ouverture }
  begin
    GetDir(0,CurrentDir);OpenDialogFitFile.InitialDir:=CurrentDir;
    pBuf:=OpenDialogFitFile.FileName;
    MultiLayerGrid.ClearNormalCells; { pour ne pas avoir de residu du système précédent, en particulier s'il contenanit plus de couches }
{ nouvelle méthode de sauvegarde }
    MultiLayerGridIO.XLSImport(pBuf,'MultiLayer');
    ParametersGridIO.XLSImport(pBuf,'Parameters');
    version:=ParametersGrid.floats[1,1];
    LambdaSpectrumGridIO.XLSImport(pbuf,'Lambda spectrum');
    ThetaSpectrumGridIO.XLSImport(pbuf,'Theta spectrum');
    ProfilesGridIO.XLSImport(pbuf,'Profiles');
    if version>=1.429  { problème si on met exactement 1.43 ?! }
    then MultiLayerGrid2IO.XLSImport(pBuf,'MultiLayer 2');
    if version>=1.489  { problème si on met exactement 1.49 ?! }
    then MDSparamsGridIO.XLSImport(pBuf,'MDSparams');
    if version<=1.499
    then begin MultiLayerGrid.Rowcount:=MultiLayerGrid.Rowcount+1;
               MultiLayerGrid2.Rowcount:=MultiLayerGrid.Rowcount+1;
               MDSparamsGrid.Rowcount:=MultiLayerGrid.Rowcount+1; end;

    FitFileName.text:=OpenDialogFitFile.FileName;
  end;
  MyExperimentalParameters.UpdateVarExpParamFromGrid(ParametersGrid,LambdaSpectrumGrid,ThetaSpectrumGrid);
  UpdateSimulReflecWindowParameters(MyExperimentalParameters);
  UpdateVarExperimentalParameters(MyExperimentalParameters);
  MyProfiles.update(ProfilesGrid);
  MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
{  MultiLayerGrid.Font.Size:=14;MultiLayerGrid.update; }
end;

procedure TSimulReflecWindow.SaveFitFile2Click(Sender: TObject);
var pBuf,currentDir:string;
begin
  UpdateVarExperimentalParameters(MyExperimentalParameters);
  MyExperimentalParameters.UpdateGridFromVarExpParam(ParametersGrid,LambdaSpectrumGrid,ThetaSpectrumGrid);
  if SaveDialogFitFile.Execute then  { Affichage de la boîte de dialogue d'ouverture }
  begin
    if FIleExists(SaveDialogFitFile.FileName) then DeleteFile(SaveDialogFitFile.FileName);
{    MultiLayerGrid.Rowcount:=MultiLayerGrid.Rowcount-1;
    MultiLayerGrid2.Rowcount:=MultiLayerGrid2.Rowcount-1;
    MDSparamsGrid.Rowcount:=MDSParamsGrid.Rowcount-1; }
    savingInProgress.visible:=true;savingInProgress.update;
    GetDir(0,CurrentDir);SaveDialogFitFile.InitialDir:=CurrentDir;
    pBuf:=SaveDialogFitFile.FileName;
{ nouvelle méthode de sauvegarde }
    MDSParamsGridIO.XLSExport(pBuf,'MDSparams');
    ProfilesGridIO.XLSExport(pbuf,'Profiles');
    ThetaSpectrumGridIO.XLSExport(pbuf,'Theta spectrum');
    LambdaSpectrumGridIO.XLSExport(pbuf,'Lambda spectrum');
    ParametersGridIO.XLSExport(pBuf,'Parameters');
    MultiLayerGrid2IO.XLSExport(pBuf,'MultiLayer 2');
    MultiLayerGridIO.XLSExport(pBuf,'MultiLayer');

    FitFileName.text:=SaveDialogFitFile.FileName;
{    MultiLayerGrid.Rowcount:=MultiLayerGrid.Rowcount+1; }
  end;
  savingInProgress.visible:=false;
  { on let a jour le repertoire de lecture des fichiers de fits }
  OpenDialogFitFile.InitialDir:=SaveDialogFitFile.InitialDir;
end;

procedure TSimulReflecWindow.SaveMLasHTML1Click(Sender: TObject);
var pBuf,currentDir:string;
begin
  if SaveDialogHTML.Execute then  { Affichage de la boîte de dialogue d'ouverture }
  begin
    GetDir(0,CurrentDir);SaveDialogHTML.InitialDir:=CurrentDir;
    pBuf:=SaveDialogHTML.FileName;
    MultiLayerGrid.saveToHTML(pBuf);
  end;
end;

procedure TSimulReflecWindow.SaveParametersasHTML1Click(Sender: TObject);
var pBuf,currentDir:string;
begin
  UpdateVarExperimentalParameters(MyExperimentalParameters);
  MyExperimentalParameters.UpdateGridFromVarExpParam(ParametersGrid,LambdaSpectrumGrid,ThetaSpectrumGrid);
  if SaveDialogHTML.Execute then  { Affichage de la boîte de dialogue d'ouverture }
  begin
    GetDir(0,CurrentDir);SaveDialogHTML.InitialDir:=CurrentDir;
    pBuf:=SaveDialogHTML.FileName;
    ParametersGrid.saveToHTML(pBuf);
  end;
end;

{ INPUT : une Column grid                                       }
{         particles : "neutrons" or "xrays"                     }
procedure TSimulReflecWindow.SetHeaders(MyEP:TExperimentalParameters;MyGrid:TAdvStringGrid);
var i:integer;
begin
   MyGRid.columnHeaders.Clear;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[0]:=colUnit*3;
   MyGrid.columnHeaders.add('Y/N');MyGrid.colWidths[colYN]:=colUnit*4;
   MyGrid.columnHeaders.add('Description');MyGrid.colWidths[colDescription]:=colUnit*14;
   MyGrid.columnHeaders.add('Thickness');MyGrid.colWidths[colEpaisseur]:=colUnit*8;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colEpaisseurYN]:=colUnit*4;
   MyGrid.columnHeaders.add('Density');MyGrid.colWidths[colDensity]:=colUnit*6;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colDensityYN]:=colUnit*4;
   if MyEP.Particles ='neutrons' then
   begin
   MyGrid.columnHeaders.add('b');MyGrid.colWidths[colB]:=colUnit*5;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colBYN]:=colUnit*4;
   MyGrid.columnHeaders.add('bi');MyGrid.colWidths[colBi]:=colUnit*5;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colBiYN]:=colUnit*4;
   MyGrid.Cells[ColB,0]:='b';MyGrid.Cells[ColBi,0]:='bi'
   end;
   if MyEP.Particles ='xrays' then
   begin
   MyGrid.columnHeaders.add('f');MyGrid.colWidths[colF]:=colUnit*5;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colFYN]:=colUnit*4;
   MyGrid.columnHeaders.add('fi');MyGrid.colWidths[colFi]:=colUnit*5;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colFiYN]:=colUnit*4;
   MyGrid.Cells[ColF,0]:='f';MyGrid.Cells[ColFi,0]:='f''';
   end;
   MyGrid.columnHeaders.add('M');MyGrid.colWidths[colM]:=colUnit*5;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colMYN]:=colUnit*4;
   MyGrid.columnHeaders.add('Theta');MyGrid.colWidths[colTheta]:=colUnit*5;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colThetaYN]:=colUnit*4;
   MyGrid.columnHeaders.add('Phi');MyGrid.colWidths[colPhi]:=colUnit*4;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colPhiYN]:=colUnit*4;
   MyGrid.columnHeaders.add('Sigma');MyGrid.colWidths[colSigma]:=colUnit*5;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colSigYN]:=colUnit*4;
   MyGrid.columnHeaders.add('Xsi');MyGrid.colWidths[colXsi]:=colUnit*0;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colXsiYN]:=colUnit*0;
   MyGrid.columnHeaders.add('h');MyGrid.colWidths[colh]:=colUnit*0;
   MyGrid.columnHeaders.add('');MyGrid.colWidths[colhYN]:=colUnit*0;
   MyGrid.columnHeaders.add('ML');MyGrid.colWidths[colMLYN]:=colUnit*4;
   MyGrid.columnHeaders.add('Profile');MyGrid.colWidths[colProfile]:=colUnit*6;
   { en tetes des lignes }
   MyGrid.rowHeaders.add('');
   for i:=1 to NbrLayersMax do MyGrid.rowHeaders.add(intTostr(i));

  { on affiche que les partamètres magnétiques pertinents }
     if MyEP.PolarisationType='non polarised'
     then with MultiLayerGrid do
                begin colWidths[colM]:=0;colWidths[colMYN]:=0;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=0;colWidths[colPhiYN]:=0;
                end;
     if MyEP.PolarisationType='polarised'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=0;colWidths[colPhiYN]:=0;
                end;
     if MyEP.PolarisationType='with spin-flip'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=colUnit*5;colWidths[colPhiYN]:=colUnit*4;
                end;
     if MyEP.PolarisationType='with SF high field'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=colUnit*5;colWidths[colThetaYN]:=colUnit*4;
                      colWidths[colPhi]:=colUnit*5;colWidths[colPhiYN]:=colUnit*4;
                end;

   with MyGrid do
   begin
      for i:=1 to NbrLayersMax do
      begin
        Colors[ColEpaisseurYN,i]:=clSilver;
        Colors[ColDensityYN,i]:=clSilver;
        Colors[ColBYN,i]:=clSilver;
        Colors[ColBiYN,i]:=clSilver;
        Colors[ColMYN,i]:=clSilver;
        Colors[ColThetaYN,i]:=clSilver;
        Colors[ColPhiYN,i]:=clSilver;
        Colors[ColSigYN,i]:=clSilver;
        Colors[ColXsiYN,i]:=clSilver;
        Colors[ColhYN,i]:=clSilver;
      end;
   end;
   MyGRid.update
end;

procedure TSimulReflecWindow.MultiLayerGridAutoDeleteRow(Sender: TObject;ARow: Integer);
begin
{   MultiLayerGrid.ClearRows(MultiLayerGrid.GetRealRow,1);
   MultiLayerGrid.RemoveRows(MultiLayerGrid.GetRealRow,1); }
{   MultiLayerGrid.AutoNumberCol(0);
   MultiLayerGrid.scrollinView(1,MultiLayerGrid.GetRealRow); }
end;

procedure TSimulReflecWindow.MultiLayerGridAutoInsertCol(Sender: TObject;ACol: Integer);
begin
  MultiLayerGrid.AutoNumberCol(0);
{  MultiLayerGrid.selectRange(1,2,1,2); }
  MultiLayerGrid.scrollinView(1,MultiLayerGrid.GetRealRow);
end;

{procedure TdataReflecForm.UpdateML1Click(Sender: TObject);
begin
    MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
end;
procedure TdataReflecForm.UpdateGridFromVar1Click(Sender: TObject);
begin
    UpdateGridFromVarExpParam(ParametersGrid,MyExperimentalParameters);
end;
procedure TdataReflecForm.UpdateVarFromGrid1Click(Sender: TObject);
begin
    UpdateVarExpParamFromGrid(MyExperimentalParameters,ParametersGrid);
end; }

procedure TSimulReflecWindow.Exit2Click(Sender: TObject);
begin
   close;
end;

{ ===========================================================}
{ ENTREES/SORTIES DE DATA SUR LE DISQUE                      }
{ ===========================================================}



procedure TSimulReflecWindow.OpenDataFileMenu2Click(Sender: TObject);
var CurrentDir:string;
begin
  if OpenDialogDataFile.Execute then
  begin
     UpdateVarExperimentalParameters(MyExperimentalParameters);
     GetDir(0,CurrentDir);SaveDialogCourbeReflec.InitialDir:=CurrentDir;
     MydataExp.ReadFromFile(MyExperimentalParameters,OpenDialogDataFile.FileName);
     SRGraph1Dform.PlotDataReflectivity(MyDataExp);
     UpdateSimulReflecWindowParameters(MyExperimentalParameters);
     DataFileName.text:=OpenDialogDataFile.FileName;
  end;
end;

procedure TSimulReflecWindow.SaveReflectivityCurveMenuClick(Sender: TObject);
var CurrentDir:string;
begin
  if SaveDialogCourbeReflec.Execute then
  begin
     UpdateVarExperimentalParameters(MyExperimentalParameters);
     GetDir(0,CurrentDir);SaveDialogCourbeReflec.InitialDir:=CurrentDir;
     MyDataCalc.SaveToFile(SaveDialogCourbeReflec.FileName);
  end;
end;

{ transfert des courbes de reflectivité dans le graph1D }
procedure TSimulReflecWindow.Transfer1DCurve(var x,z:Tvec;s:string);
var i,ind:integer;
begin
   ind:=und.addspectre(s,x.length,1,1);
   for i:=0 to x.length-1 do
   begin
      und.spect[ind].data[i,0,0].x:=x.Values[i];
      und.spect[ind].data[i,0,0].z:=z.Values[i];
   end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

procedure TSimulReflecWindow.PlotReflectivity(MyEP:TExperimentalParameters;MyDataCalc:TDataReflectivity);
var  i:integer;
     fraction1,fraction2:double;
     R,T,Rup,Rdo,Tup,Tdo,Ruu,Rdd,Rud,Rdu,Tuu,Tdd,Tud,Tdu,SA,SAExp:Tvec;
begin
   createIt(R,T);createIt(Rup,Rdo,Tup,Tdo);createIt(Ruu,Rdd,Rud,Rdu);createIt(Tuu,Tdd,Tud,Tdu);
   createIt(SA,SAexp);

   if MyEP.PolarisationType='non polarised'
   then if polydomainsMenu.checked=false
        then begin
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.R,SerieRcalcUP);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.R,'R');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.T,'T');
        {        Graph2DForm.transferCurve(Angles,T,SerieRcalcDO); }
             end
        else begin
             R.copy(MyDataCalc.R);R.Add(MyDataCalc2.R);T.copy(MyDataCalc.T);R.Add(MyDataCalc2.T);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,R,SerieRcalcUP);
             Transfer1DCurve(MyDataCalc.Abscisses,R,'R');
             Transfer1DCurve(MyDataCalc.Abscisses,T,'T');
             end;

   if MyEP.PolarisationType='polarised'
   then if polydomainsMenu.checked=false
        then begin
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,'Rup');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,'Rdo');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tup,'Tup');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdo,'Tdo');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,SerieRcalcDO);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','SA exp','-');
             SA.Copy(MyDataCalc.Rup);SAexp.Copy(MyDataExp.Rup);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Rup.values[i]-MyDataCalc.Rdo.values[i])/(MyDataCalc.Rup.values[i]+MyDataCalc.Rdo.values[i]);
             for i:=0 to MyDataExp.Abscisses.length-1 do SAexp[i]:=(MyDataExp.Rup.values[i]-MyDataExp.Rdo.values[i])/(MyDataExp.Rup.values[i]+MyDataExp.Rdo.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             SRGraph1DForm.TransferCurvePhi(MyDataExp.Abscisses,SAExp,3);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);XYGraphPhi_ReleaseUpdate(3);
             end
        else begin
             Rup.copy(MyDataCalc.Rup);Rup.Add(MyDataCalc2.Rup);Rdo.copy(MyDataCalc.Rdo);Rdo.Add(MyDataCalc2.Rdo);
             Tup.copy(MyDataCalc.Tup);Tup.Add(MyDataCalc2.Tup);Tdo.copy(MyDataCalc.Tdo);Tdo.Add(MyDataCalc2.Tdo);
             Transfer1DCurve(MyDataCalc.Abscisses,Rup,'Rup');Transfer1DCurve(MyDataCalc.Abscisses,Rdo,'Rdo');
             Transfer1DCurve(MyDataCalc.Abscisses,Tup,'Tup');Transfer1DCurve(MyDataCalc.Abscisses,Tdo,'Tdo');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rup,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdo,SerieRcalcDO);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Rup);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Rup.values[i]-MyDataCalc.Rdo.values[i])/(MyDataCalc.Rup.values[i]+MyDataCalc.Rdo.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   if MyEP.PolarisationType='with spin-flip'
   then if polydomainsMenu.checked=false
        then begin
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSF);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end
        else begin
             Ruu.copy(MyDataCalc.Ruu);Ruu.Add(MyDataCalc2.Ruu);Rdd.copy(MyDataCalc.Rdd);Rdd.Add(MyDataCalc2.Rdd);Rud.copy(MyDataCalc.Rud);Rud.Add(MyDataCalc2.Rud);
             Tuu.copy(MyDataCalc.Tuu);Tuu.Add(MyDataCalc2.Tuu);Tdd.copy(MyDataCalc.Tdd);Tdd.Add(MyDataCalc2.Tdd);Tud.copy(MyDataCalc.Tud);Tud.Add(MyDataCalc2.Tud);

             Transfer1DCurve(MyDataCalc.Abscisses,Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rud,SerieRcalcSF);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   if MyEP.PolarisationType='with SF high field'
   then if polydomainsMenu.checked=false
        then begin
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSFUD);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdu,SerieRcalcSFDU);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end
        else begin
             Ruu.copy(MyDataCalc.Ruu);Ruu.Add(MyDataCalc2.Ruu);Rdd.copy(MyDataCalc.Rdd);Rdd.Add(MyDataCalc2.Rdd);Rud.copy(MyDataCalc.Rud);Rud.Add(MyDataCalc2.Rud);
             Tuu.copy(MyDataCalc.Tuu);Tuu.Add(MyDataCalc2.Tuu);Tdd.copy(MyDataCalc.Tdd);Tdd.Add(MyDataCalc2.Tdd);Tud.copy(MyDataCalc.Tud);Tud.Add(MyDataCalc2.Tud);

             Transfer1DCurve(MyDataCalc.Abscisses,Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSFUD);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdu,SerieRcalcSFDU);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   
   freeIt(R,T);freeIt(Rup,Rdo,Tup,Tdo);freeIt(Ruu,Rdd,Rud,Rdu);freeIt(Tuu,Tdd,Tud,Tdu);freeIt(SA);
end;

{ procedure de calcul d'une courbe de réflectivvité }
{ INPUT: uniquement implicites                      }
{ OUTPUT: R une courbe de réflectivité              }
{         on peut tenir compte ou non d'une largeur en lambda }
{ ATTENTION: calcul complètement incohérent!!!      }
{            Rtotale = Sum (R(lambda))              }
procedure TSimulReflecWindow.CalculateReflectivity1Click(Sender: TObject);
var  i:integer;
     fraction1,fraction2:double;
     R,T,Rup,Rdo,Tup,Tdo,Ruu,Rdd,Rud,Rdu,Tuu,Tdd,Tud,Tdu,SA,SAExp:Tvec;
begin
   createIt(R,T);createIt(Rup,Rdo,Tup,Tdo);createIt(Ruu,Rdd,Rud,Rdu);createIt(Tuu,Tdd,Tud,Tdu);
   createIt(SA,SAexp);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataCalc.updateWithRange(MyExperimentalParameters);

   If polydomainsMenu.checked=true
   then begin
        MyMultiLayer2.UpdateFromMultiLayerGrid(MultiLayerGrid2,MyExperimentalParameters);
        MyDataCalc2.updateWithRange(MyExperimentalParameters);
        fraction1:=fraction1Box.value/(fraction1Box.value+fraction2Box.value);
        fraction2:=fraction2Box.value/(fraction1Box.value+fraction2Box.value);
        end;

   if typePolarisation.text='non polarised'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.R,SerieRcalcUP);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.R,'R');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.T,'T');
        {        Graph2DForm.transferCurve(Angles,T,SerieRcalcDO); }
             end
        else begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
             R.copy(MyDataCalc.R);R.Add(MyDataCalc2.R);T.copy(MyDataCalc.T);T.Add(MyDataCalc2.T);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,R,SerieRcalcUP);
             Transfer1DCurve(MyDataCalc.Abscisses,R,'R');
             Transfer1DCurve(MyDataCalc.Abscisses,T,'T');
             end;

   if typePolarisation.text='polarised'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,'Rup');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,'Rdo');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tup,'Tup');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdo,'Tdo');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,SerieRcalcDO);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','SA exp','-');
             SA.Copy(MyDataCalc.Rup);SAexp.Copy(MyDataExp.Rup);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Rup.values[i]-MyDataCalc.Rdo.values[i])/(MyDataCalc.Rup.values[i]+MyDataCalc.Rdo.values[i]);
             for i:=0 to MyDataExp.Abscisses.length-1 do SAexp[i]:=(MyDataExp.Rup.values[i]-MyDataExp.Rdo.values[i])/(MyDataExp.Rup.values[i]+MyDataExp.Rdo.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             SRGraph1DForm.TransferCurvePhi(MyDataExp.Abscisses,SAExp,3);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);XYGraphPhi_ReleaseUpdate(3);
             end
        else begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
             Rup.copy(MyDataCalc.Rup);Rup.Add(MyDataCalc2.Rup);Rdo.copy(MyDataCalc.Rdo);Rdo.Add(MyDataCalc2.Rdo);
             Tup.copy(MyDataCalc.Tup);Tup.Add(MyDataCalc2.Tup);Tdo.copy(MyDataCalc.Tdo);Tdo.Add(MyDataCalc2.Tdo);

             Transfer1DCurve(MyDataCalc.Abscisses,Rup,'Rup');Transfer1DCurve(MyDataCalc.Abscisses,Rdo,'Rdo');
             Transfer1DCurve(MyDataCalc.Abscisses,Tup,'Tup');Transfer1DCurve(MyDataCalc.Abscisses,Tdo,'Tdo');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rup,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdo,SerieRcalcDO);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Rup);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Rup.values[i]-MyDataCalc.Rdo.values[i])/(MyDataCalc.Rup.values[i]+MyDataCalc.Rdo.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   if typePolarisation.text='with spin-flip'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSF);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end
        else begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
             Ruu.copy(MyDataCalc.Ruu);Ruu.Add(MyDataCalc2.Ruu);Rdd.copy(MyDataCalc.Rdd);Rdd.Add(MyDataCalc2.Rdd);Rud.copy(MyDataCalc.Rud);Rud.Add(MyDataCalc2.Rud);
             Tuu.copy(MyDataCalc.Tuu);Tuu.Add(MyDataCalc2.Tuu);Tdd.copy(MyDataCalc.Tdd);Tdd.Add(MyDataCalc2.Tdd);Tud.copy(MyDataCalc.Tud);Tud.Add(MyDataCalc2.Tud);

             Transfer1DCurve(MyDataCalc.Abscisses,Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rud,SerieRcalcSF);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   if typePolarisation.text='with SF high field'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSFUD);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdu,SerieRcalcSFDU);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end
        else begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
             Ruu.copy(MyDataCalc.Ruu);Ruu.Add(MyDataCalc2.Ruu);Rdd.copy(MyDataCalc.Rdd);Rdd.Add(MyDataCalc2.Rdd);Rud.copy(MyDataCalc.Rud);Rud.Add(MyDataCalc2.Rud);
             Tuu.copy(MyDataCalc.Tuu);Tuu.Add(MyDataCalc2.Tuu);Tdd.copy(MyDataCalc.Tdd);Tdd.Add(MyDataCalc2.Tdd);Tud.copy(MyDataCalc.Tud);Tud.Add(MyDataCalc2.Tud);

             Transfer1DCurve(MyDataCalc.Abscisses,Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSFUD);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdu,SerieRcalcSFDU);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   MyDataCalc.SaveToClipboard;
   freeIt(R,T);freeIt(Rup,Rdo,Tup,Tdo);freeIt(Ruu,Rdd,Rud,Rdu);freeIt(Tuu,Tdd,Tud,Tdu);freeIt(SA);
end;

procedure TSimulReflecWindow.CalculateReflectivityPhase2Click(Sender: TObject);
var  i:integer;
     Phi,PhiUp,PhiDo:Tvec;
begin
   createIt(Phi,PhiUp,PhiDo);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataCalc.updateWithRange(MyExperimentalParameters);

   if typePolarisation.text='non polarised'
   then begin
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
        MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
        SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.R,SerieRcalcUP);
{        Graph2DForm.transferCurve(Angles,T,SerieRcalcDO); }
        CalculAmplitudeNP(MyDataCalc.Qz,MyMultiLayer.z,MyMultiLayer.V,MyMultiLayer.Vi,MyMultiLayer.sigma,MyDataCalc.AR,MyDataCalc.AT);
        SetLegendXYGraphPhi('SPECULAR REFLECTIVITY PHASE','phase','-','-','-');
        Phi.Copy(MyDataCalc.AR); { pour initialiser le vecteur Phi }
        for i:=0 to MyDataCalc.Abscisses.length-1 do Phi[i]:=Arg(MyDataCalc.AR.Cvalues[i])*180/pi;
        SRGraph1DForm.transferCurvePhi(MyDataCalc.Abscisses,phi,SeriePhaseUP);
        XYGraphPhi_ReleaseUpdate(SeriePhaseUP);

        Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.R,'R');
        Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.T,'T');
        Transfer1DCurve(MyDataCalc.Abscisses,Phi,'Phi');
        end;
   if typePolarisation.text='polarised'
   then begin
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
        MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
        SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,SerieRcalcUP);
        SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,SerieRcalcDO);

        SetLegendXYGraphPhi('SPECULAR REFLECTIVITY PHASE','phase UP','phase DO','-','-');
        {  partie phases  des reflectivités }
        CalculAmplitudeNP(MyDataCalc.Qz,MyMultiLayer.z,MyMultiLayer.Vup,MyMultiLayer.Vi,MyMultiLayer.sigma,MyDataCalc.AR,MyDataCalc.AT);
        PhiUp.Copy(MyDataCalc.AR); { pour initialiser le vecteur Phi }
        for i:=0 to MyDataCalc.Abscisses.length-1 do PhiUp[i]:=Arg(MyDataCalc.AR.Cvalues[i])*180/pi;
        SRGraph1DForm.transferCurvePhi(MyDataCalc.Abscisses,phiUp,SeriePhaseUP);
        XYGraphPhi_ReleaseUpdate(SeriePhaseUP);

        CalculAmplitudeNP(MyDataCalc.Qz,MyMultiLayer.z,MyMultiLayer.Vdo,MyMultiLayer.Vi,MyMultiLayer.sigma,MyDataCalc.AR,MyDataCalc.AT);
        PhiDo.Copy(MyDataCalc.AR); { pour initialiser le vecteur Phi }
        for i:=0 to MyDataCalc.Abscisses.length-1 do PhiDo[i]:=Arg(MyDataCalc.AR.Cvalues[i])*180/pi;
        SRGraph1DForm.transferCurvePhi(MyDataCalc.Abscisses,phiDo,SeriePhaseDO);
        XYGraphPhi_ReleaseUpdate(SeriePhaseDO);

        Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,'Rup');
        Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tup,'Tup');
        Transfer1DCurve(MyDataCalc.Abscisses,Phiup,'PhiUp');
        Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,'Rdo');
        Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdo,'Tdo');
        Transfer1DCurve(MyDataCalc.Abscisses,Phido,'PhiDo');

        end;
   freeIt(Phi,PhiUp,PhiDo);
end;

{ calcul de la différence entre la courbe mesurée et la courbe calculée }
{ on plotte la courbe abs(Rexp-Rcalc)/(Rexp-Rcalc) sur le graph XYgraphPhi }
{ INPUT: 100% implicite                                                    }
{ OUTPUT: on plotte la différence des courbes expérimentale et calculées sur le graphPhi }
{         (R-Rexp)/(R+Rexp)                                                              }
{ REMARQUE: IL FAUT AVOIR CHARGE UN FICHIER DE DATA !!!                                  }
procedure TSimulReflecWindow.CalculateDifference2Click(Sender: TObject);
var diff,diffSmooth:double;
    fraction1,fraction2:double;
begin
{   SRGraph1DForm.storeCurves; }
   { on copie les dataExp et on les crops }
   MyDataExpFit.clone(MyDataExp);
   MydataExpFit.crop(FitAbsMin.value,FitAbsMax.value);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataExpFit.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc.abscisses.copy(MyDataExpFit.abscisses);
   MyDataCalc.updateWithAbscisses(MyExperimentalParameters);
   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);

   if PolydomainsMenu.Checked=true
   then begin
        MyMultiLayer2.UpdateFromMultiLayerGrid(MultiLayerGrid2,MyExperimentalParameters);
        MyDataCalc2.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc2.updateWithAbscisses(MyExperimentalParameters);
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);
        MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
        { normalisation aditionnelle pour le taux de domaines }
        fraction1:=fraction1Box.value/(fraction1Box.value+fraction2Box.value);
        fraction2:=fraction2Box.value/(fraction1Box.value+fraction2Box.value);
        MyDataCalc.Normalise(fraction1);MyDataCalc2.Normalise(fraction2);
        { Addition des réflectivités }
        With MyDataCalc do
          begin R.Add(MyDataCalc2.R);T.Add(MyDataCalc2.T);
              Rup.Add(MyDataCalc2.Rup);Rdo.Add(MyDataCalc2.Rdo);Tup.Add(MyDataCalc2.Tup);Tdo.Add(MyDataCalc2.Tdo);
              Ruu.Add(MyDataCalc2.Ruu);Rdd.Add(MyDataCalc2.Rdd);Rud.Add(MyDataCalc2.Rud);Rdu.Add(MyDataCalc2.Rdu);
              Tuu.Add(MyDataCalc2.Tuu);Tdd.Add(MyDataCalc2.Tdd);Tud.Add(MyDataCalc2.Tud);Tdu.Add(MyDataCalc2.Tdu);
          end;
        end;

   SRGraph1Dform.PlotDifference(MyDataExpFit,MyDataCalc);
   diff:=difference(MyDataExpFit,MyDataCalc,MyExperimentalParameters);ecartBox.value:=diff;
   if MyMultiLayer.profiled
   then begin diffSmooth:=MyMultiLayer.SmoothProfile(MyProfiles);
              ecartBoxSmooth.value:=diffSmooth;
              ecartBox.value:=diff+diffSmooth  end;
   MyDataCalc.SaveToClipboard;
end;

{ minimisation par la méthode basique du "crawling" }
procedure TSimulReflecWindow.FitCrawlingMenuClick(Sender: TObject);
var i:integer;
    t0:TDateTime;
begin
{   SRGraph1DForm.storeCurves; }
   MyDataExpFit.clone(MyDataExp);
   MydataExpFit.crop(FitAbsMin.value,FitAbsMax.value);
   { mise a jour des paramètres experimentaux a partir des informations de la fenetre graphique}
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   { mise a jour des resolutions expérimentales }
   MyDataExpFit.updateWithAbscisses(MyExperimentalParameters);
   { on crée le spectre des data calculées }
   MyDataCalc.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc.updateWithAbscisses(MyExperimentalParameters); { mise a jour des paramètres de résolution }

   { on affiche le panneau de fit }
   TabSheetFitting.Tabvisible:=true;PageControl.update;
   t0:=time;
   if TypePolarisation.text='non polarised' then  MinimisationCrawling(RandomnessBox.value,MyExperimentalParameters,MyMultiLayer,MyProfiles,MyDataExpFit,MyDataCalc);
   if TypePolarisation.text='polarised' then  MinimisationCrawling_P(RandomnessBox.value,MyExperimentalParameters,MyMultiLayer,MyProfiles,MyDataExpFit,MyDataCalc);
   if TypePolarisation.text='with spin-flip' then  MinimisationCrawling_SF(RandomnessBox.value,MyExperimentalParameters,MyMultiLayer,MyProfiles,MyDataExpFit,MyDataCalc);
   if TypePolarisation.text='with SF high field' then  MinimisationCrawling_SF_HF(RandomnessBox.value,MyExperimentalParameters,MyMultiLayer,MyProfiles,MyDataExpFit,MyDataCalc);

{ affichage des résultats }
   { mise a jour des courbes }
   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);

{ cas particulier éventuel d'un fit de data mesurées en neutrons non polarisés sur un échantillon magnétique }
   if dataFittingOptionsBox.itemIndex=3
   then begin
        { il faut sommer MyDataCalc.Rup et Rdo }
        MyDataCalc.R.length:=MyDataCalc.Rup.length;
        for i:=0 to MyDataCalc.R.length-1 do
           begin MyDataCalc.R[i]:=(MyDataCalc.Rup[i]+MyDataCalc.Rdo[i])/2;
                 MyDataCalc.Rup[i]:=MyDataCalc.R[i];MyDataCalc.Rdo[i]:=MyDataCalc.R[i]; end;
        end;

   SRGraph1Dform.PlotDifference(MyDataExp,MyDataCalc);
   FittingStatus.caption:='Idle';FittingStatus.update;
   IterCrt.caption:='...';IterCrt.update;
   ecartBox.value:=difference(MyDataExpFit,MyDataCalc,MyExperimentalParameters);
   if MyMultiLayer.profiled then begin ecartBoxSmooth.value:=MyMultiLayer.SmoothProfile(MyProfiles);ecartBox.value:=ecartBox.value+ecartBoxSmooth.value end;

   { cas particulier d'un fit sur le Cos PHI }
   if ((TypePolarisation.text='with spin-flip') or (TypePolarisation.text='with SF high field')) and (dataFittingOptionsBox.itemIndex=5) then CosPhiDifference;
   if ((TypePolarisation.text='with spin-flip') or (TypePolarisation.text='with SF high field')) and (dataFittingOptionsBox.itemIndex=6) then SinPhiDifference;

   ElapsedTimeBox.Value:=(time-t0)*86400;
   MyDataCalc.SaveToClipboard;
   PlayWave('The_Fit_Is_Finished');
end;

procedure TSimulReflecWindow.FitCrawlingRandomMenuClick(Sender: TObject);
var t0:TDateTime;
begin

end;

{ initialisation des paramètres Libres du MDS                                   }
{ INPUT : le tableau des MDS_ML                                                 }
{ OUTPUT : les paramètres des MDS_ML sont mis a jour à partir du tableau        }
function TSimulReflecWindow.updateMDS_MLfromGrid(var MyMDS_ML:array of TMultiLayer;var MyEP:TexperimentalParameters):integer;
var i,j,colIdx:integer;
    toto:double;
begin
   { mise à jour des paramètres libres pour chaque ML   }
   { à partir du tableau 'MDSparameters'                }
   { + il faut faire une première initialisation ors du premier lancement }
   result:=0;
   if MDSparamsGrid.floats[1,1]=0
   then begin MessageDlg('You have not initialized the free parameters of your multi-fit', mtInformation, [mbOk], 0);result:=-1;exit; end;
   for i:=0 to high(MyMDS) do
   begin
      colIdx:=1;
      MDSparamsGrid.ints[0,i+1]:=i+1; { index du MDS }
      with MyMDS_ML[i] do
      begin
          for j:=0 to nbrLayers-1 do
          begin
             if zYN[j]<>-1 then if zCorr[j]='L' then begin z[j]:=MDSparamsGrid.floats[colidx,i+1]*1e-9;inc(colidx) end;
             if dYN[j]<>-1 then if dCorr[j]='L' then begin d[j]:=MDSparamsGrid.floats[colidx,i+1]*1e28;inc(colidx)  end;
             if MyEP.particles='neutrons'
             then begin
                  if bYN[j]<>-1 then if bCorr[j]='L'
                                     then begin bn[j]:=MDSparamsGrid.floats[colidx,i+1]*1e-15;inc(colidx) end;
                  if biYN[j]<>-1 then if biCorr[j]='L' then begin bni[j]:=MDSparamsGrid.floats[colidx,i+1]*1e-15;inc(colidx) end;
                  if MyEP.polarisationType='polarised'
                  then if MYN[j]<>-1 then if MCorr[j]='L' then begin Aim[j]:=MDSparamsGrid.floats[colidx,i+1]*(mu0*muB*d[j]);inc(colidx) end;
                  if (MyEP.polarisationType='with spin-flip') or (MyEP.polarisationType='with SF high field')
                  then begin
                       if MYN[j]<>-1 then if MCorr[j]='L' then begin Aim[j]:=MDSparamsGrid.floats[colidx,i+1]*(mu0*muB*d[j]);inc(colidx) end;
                       if ThetaYN[j]<>-1 then if ThetaCorr[j]='L' then begin Theta[j]:=MDSparamsGrid.floats[colidx,i+1]*pi/180;inc(colidx) end;
                       if PhiYN[j]<>-1 then if PhiCorr[j]='L' then begin Phi[j]:=MDSparamsGrid.floats[colidx,i+1]*pi/180;inc(colidx) end;
                       end;
                  end
             else begin
                  if fYN[j]<>-1 then if fCorr[j]='L' then begin f[j]:=MDSparamsGrid.floats[colidx,i+1];inc(colidx) end;
                  if fiYN[j]<>-1 then if fiCorr[j]='L' then begin fi[j]:=MDSparamsGrid.floats[colidx,i+1];inc(colidx) end;
                  end;
             if sigYN[j]<>-1 then if sigmaCorr[j]='L' then begin sigma[j]:=MDSparamsGrid.floats[colidx,i+1]*1e-9;inc(colidx) end;
          end;
      end;
{      EditReal3.value:=toto; }
   end;
end;

{ lancement d'un fit sur des MDS }
{ on fait l'hypothèse que les conditions expérimentales sont les mêmes pour toutes les data }
procedure TSimulReflecWindow.FitCrawlingMDSmenuClick(Sender: TObject);
var i:integer;
    t0:TDateTime;
    diff:double;
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);  { on garde la variable globale MyEP dans ce cas précis puisque toutes les data utilisent le même }
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   { on copie les dataExp et on les crops , pour tous les datas sets; attention un seul crop pour toutes les data }
   for i:=0 to high(MyMDS) do
   begin
      setlength(MyMDSfit,i+1);MyMDSfit[i]:=TDataReflectivity.create;
      MyMDSFit[i].clone(MyMDS[i]);
      MyMDSFit[i].crop(FitAbsMin.value,FitAbsMax.value);
      { on crée le spectre des data calculées }
      setlength(MyMDS_DataCalc,i+1);MyMDS_DataCalc[i]:=TDataReflectivity.create;
      MyMDS_DataCalc[i].abscisses.copy(MyMDSFit[i].abscisses);
      MyMDS_DataCalc[i].updateWithAbscisses(MyExperimentalParameters);       { mise a jour des resolutions expérimentales }
   end;
   MyProfiles.update(ProfilesGrid);  { est-ce compatible avec les MDS ?}

   { on recopie la MultiLayer pour chaque dataSet }
   for i:=0 to high(MyMDS) do MyMDS_ML[i].Clone(MyMultiLayer);

   { rafraichissement des headers des colonnes }
   UPdateMDSGridColHeaders(MyMDS_ML,MyExperimentalParameters);
   if updateMDS_MLfromGrid(MyMDS_ML,MyExperimentalParameters)<>0 then exit;

{ TEMPORAIRE }
{   diff:=999;updateDisplayWhileFitting(MultiLayerGrid,MyMDS_ML[MDSIndexBox.value-1],MyExperimentalParameters,diff);exit; }

   { on affiche le panneau de fit }
   TabSheetFitting.Tabvisible:=true;PageControl.update;
   t0:=time;
   if TypePolarisation.text='non polarised' then  MinimisationCrawlingMDS(0,MyExperimentalParameters,MyMDS_ML,MyProfiles,MyMDSfit,MyMDS_dataCalc);
   if TypePolarisation.text='polarised' then  MinimisationCrawlingMDS_P(0,MyExperimentalParameters,MyMDS_ML,MyProfiles,MyMDSfit,MyMDS_dataCalc);
{   if TypePolarisation.text='with spin-flip' then  MinimisationCrawling_SF(0,MyExperimentalParameters,MyMultiLayer,MyDataExpFit,MyDataCalc);
   if TypePolarisation.text='with SF high field' then  MinimisationCrawlingMDS_SF_HF(0,MyExperimentalParameters,MyMultiLayer,MyDataExpFit,MyDataCalc); }
   ElapsedTimeBox.Value:=(time-t0)*86400;
{ mise a jour des courbes }
   diff:=0;
   for i:=0 to high(MyMDS) do
   begin
      CalculateReflectivity(MyExperimentalParameters,MyMDS_ML[i],MyMDS_DataCalc[i]);
{   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor); }
     diff:=diff+difference(MyMDSfit[i],MyMDS_DataCalc[i],MyExperimentalParameters);
   end;
   ecartBox.value:=diff;
   UpdateMDSfreeParams(MyMDS_ML,MyExperimentalParameters);
   SRGraph1Dform.PlotDifference(MyMDS[MDSIndexBox.value-1],MyMDS_DataCalc[MDSIndexBox.value-1]);
   FittingStatus.caption:='Idle';FittingStatus.update;
   IterCrt.caption:='...';IterCrt.update;
{ TEMPORAIRE!!} {   if MyMultiLayer.profiled then begin ecartBoxSmooth.value:=MyMultiLayer.SmoothProfile(MyProfiles);ecartBox.value:=ecartBox.value+ecartBoxSmooth.value end; }
   ElapsedTimeBox.Value:=(time-t0)*86400;
{   MyDataCalc.SaveToClipboard; }
   PlayWave('The_Fit_Is_Finished');
end;


procedure TSimulReflecWindow.Insertnewlayer1Click(Sender: TObject);
var rowNr:integer;
    col: TGridColumnItem;
begin
   rowNr:=MultiLayerGrid.GetRealRow;
   MultiLayerGrid.InsertRows(rowNr,1);
   MultiLayerGrid.AutoNumberCol(0);MultiLayerGrid.Alignments[0,rowNr] := taLeftJustify;
{  MultiLayerGrid.selectRange(1,2,1,2); }
   MultiLayerGrid.scrollinView(1,MultiLayerGrid.GetRealRow);
   { remplissage de la nouvelle ligne }
   rowNr:=MultiLayerGrid.GetRealRow;MultiLayerGrid.Alignments[0,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColYN,rowNr]:='Y';
   MultiLayerGrid.Cells[ColDescription,rowNr]:='MyNewLayer';
   MultiLayerGrid.Cells[ColEpaisseur,rowNr]:='10';MultiLayerGrid.Alignments[ColEpaisseur,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColEpaisseurYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColDensity,rowNr]:='10';MultiLayerGrid.Alignments[ColDensity,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColDensityYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColB,rowNr]:='10';MultiLayerGrid.Alignments[ColB,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColBYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColBi,rowNr]:='0';MultiLayerGrid.Alignments[ColBi,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColBiYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColM,rowNr]:='0';MultiLayerGrid.Alignments[ColM,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColMYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColTheta,rowNr]:='90';MultiLayerGrid.Alignments[ColTheta,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColThetaYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColPhi,rowNr]:='0';MultiLayerGrid.Alignments[ColPhi,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColPhiYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColSigma,rowNr]:='0.3';MultiLayerGrid.Alignments[ColSigma,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColSigYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColXsi,rowNr]:='0';MultiLayerGrid.Alignments[ColXsi,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColXsiYN,rowNr]:='N';
   MultiLayerGrid.Cells[Colh,rowNr]:='0';MultiLayerGrid.Alignments[Colh,rowNr] := taLeftJustify;
   MultiLayerGrid.Cells[ColhYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColMLYN,rowNr]:='N';
   MultiLayerGrid.Cells[ColProfile,rowNr]:='0';MultiLayerGrid.Alignments[ColProfile,rowNr] := taLeftJustify;

{   MultiLayerGrid.SelectRows(1,2);
   MultiLayerGrid.font.Color:=clred; }
end;

procedure TSimulReflecWindow.Deleteselectedlayer1Click(Sender: TObject);
begin
if PageControl1.activePage=ML1
then begin
   MultiLayerGrid.ClearRows(MultiLayerGrid.GetRealRow,1);
   MultiLayerGrid.RemoveRows(MultiLayerGrid.GetRealRow,1);
   MultiLayerGrid.AutoNumberCol(0);
{  MultiLayerGrid.selectRange(1,2,1,2); }
   MultiLayerGrid.scrollinView(1,MultiLayerGrid.GetRealRow);
   end;
if PageControl1.activePage=ML2
then begin
   MultiLayerGrid2.ClearRows(MultiLayerGrid2.GetRealRow,1);
   MultiLayerGrid2.RemoveRows(MultiLayerGrid2.GetRealRow,1);
   MultiLayerGrid2.AutoNumberCol(0);
{  MultiLayerGrid.selectRange(1,2,1,2); }
   MultiLayerGrid2.scrollinView(1,MultiLayerGrid2.GetRealRow);
   end;
end;

procedure TSimulReflecWindow.Copyselectedlayer1Click(Sender: TObject);
begin
   MultiLayerGrid.CopySelectionToClipBoard;
   MultiLayerGrid.AutoNumberCol(0);
{  MultiLayerGrid.selectRange(1,2,1,2); }
   MultiLayerGrid.scrollinView(1,MultiLayerGrid.GetRealRow);
end;

procedure TSimulReflecWindow.Pasteselectedlayer1Click(Sender: TObject);
begin
   MultiLayerGrid.PasteSelectionFromClipBoard;
   MultiLayerGrid.AutoNumberCol(0);
{  MultiLayerGrid.selectRange(1,2,1,2); }
   MultiLayerGrid.scrollinView(1,MultiLayerGrid.GetRealRow);
end;

procedure TSimulReflecWindow.CopyDatatoClipboard1Click(Sender: TObject);
begin
    MyDataCalc.SaveToClipboard;
end;

procedure TSimulReflecWindow.PasteDatafromClipboard1Click(Sender: TObject);
begin
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyDataExp.UpdateWithAbscisses(MyExperimentalParameters);
   MyDataExp.ReadFromClipboard(MyExperimentalParameters);
   SRGraph1Dform.PlotDataReflectivity(MyDataExp)
end;

procedure TSimulReflecWindow.OpenLambdaSpectrum2Click(Sender: TObject);
var
  i,errorcode:integer;
  nbrPointsExp:integer; { nombre de points expérimentaux }
  indiceValeur:integer; { indice de la valeur dans la ligne de texte }
  F: TextFile;
  S,S1: string[255];
  aux:double;
  valeurs:array[1..10] of double; { valeurs numériques lues sur la ligne }
  finChaine:boolean;
  totalIntensity:double;
  currentDir:string;
begin
  MyExperimentalParameters.lambdaSpectrum.size(nbrConvMax,false);
  MyExperimentalParameters.lambdaIntensity.size(nbrConvMax,false);
  if OpenDialogLambdaSpectrum.Execute then  { Affichage de la boîte de dialogue d'ouverture }
  begin
    AssignFile(F, OpenDialogLambdaSpectrum.FileName);{ Fichier sélectionné dans la boîte de dialogue }
    GetDir(0,CurrentDir);OpenDialoglambdaSPectrum.InitialDir:=CurrentDir;
    Reset(F);
    for i:=1 to lambdaHeaderLength.value do readln(F,s); { on se débarasse de l'en-tête }
    nbrPointsExp:=0;
    totalIntensity:=0;
    while not(Eof(F)) do { lecture des data du fichier }
    begin
        Readln(F, S);    { Lecture de la première ligne du fichier }
        { traitement de la chaine pour en extraire les nombres }
        S1:='';i:=1;finChaine:=false;indiceValeur:=1;
        while not FinChaine do
        begin
             s1:='';
             while (S[i]<>#9) and (S[i]<>',') and (i<=length(S)) do {#9 est un caractère tab , #10 est LF}
             begin
                  s1:=s1+s[i];i:=i+1;
             end;
             if i>length(S) then FinChaine:=true;
             i:=i+1;{ on saute le tab ou la virgule }
             val(s1,aux,ErrorCode);valeurs[indiceValeur]:=aux;
             indiceValeur:=indiceValeur+1;
        end;
        { remplissage des vecteurs en fonction de la situation }
        { non polarisé OU polaisé OU polarisé avec analyse de polarisation }
        MyExperimentalParameters.lambdaSpectrum[nbrPointsExp]:=valeurs[1]*1e-9;
        MyExperimentalParameters.lambdaIntensity[nbrPointsExp]:=valeurs[2];
        TotalIntensity:=TotalIntensity+valeurs[2];
        nbrPointsExp:=nbrPointsExp+1;
    end;
    MyExperimentalParameters.lambdaSpectrum.size(nbrPointsExp,false);
    MyExperimentalParameters.lambdaIntensity.size(nbrPointsExp,false);
    MyExperimentalParameters.lambdaIntensity.scale(1/TotalIntensity);
    CloseFile(F);
    LambdaDistChoice.ItemIndex:=1;
  end;
  MyExperimentalParameters.UpdateGridFromVarExpParam(ParametersGrid,LambdaSpectrumGrid,ThetaSpectrumGrid);
end;

procedure TSimulReflecWindow.OpenThetaSpectrum2Click(Sender: TObject);
var
  i,errorcode:integer;
  nbrPointsExp:integer; { nombre de points expérimentaux }
  indiceValeur:integer; { indice de la valeur dans la ligne de texte }
  F: TextFile;
  S,S1: string[255];
  aux:double;
  valeurs:array[1..10] of double; { valeurs numériques lues sur la ligne }
  finChaine:boolean;
  totalIntensity:double;
  currentDir:string;
begin
  MyExperimentalParameters.thetaSpectrum.size(nbrConvMax,false);
  MyExperimentalParameters.thetaIntensity.size(nbrConvMax,false);
  if OpenDialogThetaSpectrum.Execute then  { Affichage de la boîte de dialogue d'ouverture }
  begin
    AssignFile(F, OpenDialogThetaSpectrum.FileName);{ Fichier sélectionné dans la boîte de dialogue }
    GetDir(0,CurrentDir);OpenDialogThetaSpectrum.InitialDir:=CurrentDir;
    Reset(F);
    for i:=1 to thetaHeaderLength.value do readln(F,s); { on se débarasse de l'en-tête }
    nbrPointsExp:=0;
    totalIntensity:=0;
    while not(Eof(F)) do { lecture des data du fichier }
    begin
        Readln(F, S);    { Lecture de la première ligne du fichier }
        { traitement de la chaine pour en extraire les nombres }
        S1:='';i:=1;finChaine:=false;indiceValeur:=1;
        while not FinChaine do
        begin
             s1:='';
             while (S[i]<>#9) and (S[i]<>',') and (i<=length(S)) do {#9 est un caractère tab , #10 est LF}
             begin
                  s1:=s1+s[i];i:=i+1;
             end;
             if i>length(S) then FinChaine:=true;
             i:=i+1;{ on saute le tab ou la virgule }
             val(s1,aux,ErrorCode);valeurs[indiceValeur]:=aux;
             indiceValeur:=indiceValeur+1;
        end;
        { remplissage des vecteurs en fonction de la situation }
        { non polarisé OU polaisé OU polarisé avec analyse de polarisation }
        MyExperimentalParameters.thetaSpectrum[nbrPointsExp]:=valeurs[1]*pi/180;
        MyExperimentalParameters.thetaIntensity[nbrPointsExp]:=valeurs[2];
        TotalIntensity:=TotalIntensity+valeurs[2];
        nbrPointsExp:=nbrPointsExp+1;
    end;
    MyExperimentalParameters.thetaSpectrum.size(nbrPointsExp,false);
    MyExperimentalParameters.thetaIntensity.size(nbrPointsExp,false);
    MyExperimentalParameters.thetaIntensity.scale(1/TotalIntensity);
    CloseFile(F);
    ThetaDistChoice.ItemIndex:=1;
  end;
end;

procedure TSimulReflecWindow.StabilityPlotButtonClick(Sender: TObject);
var ind,idxLayer, idxLayer1, idxLayer2, i, j:integer;
    diff,para1Value,deltaPara1,para2Value,deltaPara2:double;

procedure MiseAjourPotentiels;
var i:integer;
begin
   with MyMultiLayer do
   begin
{      nbrLayers:=z.length; }
      for i:=0 to nbrLayers-1 do
      begin
        if MyExperimentalParameters.particles='neutrons'
        then begin
                V[i]:=Pihm*d[i]*bn[i];Vi[i]:=-Pihm*d[i]*bni[i];
                Vup[i]:=V[i]-Aim[i]*mun;Vdo[i]:=V[i]+Aim[i]*mun; end;
        if MyExperimentalParameters.particles='xrays'
        then begin
                V[i]:=Cte*d[i]*f[i];Vi[i]:=-Cte*d[i]*fi[i] end;
      end;
   end;
end;

begin
{ ============================================================ }
   StabilityPlotStatus.caption:='Calculating...';StabilityPlotStatus.update;
{ ============================================================ }
{ on suit la meme demarche que pour le calcul de la différence }
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataExp.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc.abscisses.copy(MyDataExp.abscisses);MyDataCalc.updateWithAbscisses(MyExperimentalParameters); { mise a jour des paramètres de résolution }
   { il faut regenere les abscisses avec les paramètres de convolution }

{ on fait varier le paramètre 1 }
if (para1checkbox.checked=true)
then begin
        ind:=und.addspectre('stabilityP1',Para1mesh.value+1,1,1);
        i:=0; while (MyMultiLayer.layerIdx[i]<>para1LayerNumber.value) and  (i<nbrlayersMax) do inc(i);
        if (i=nbrLayersMax)
        then MessageDlg('Layer does not exist!', mtInformation, [mbOk], 0)
        else begin
        idxLayer:=i;
        { on suppose qu'on dispose d'un tableau de data Rexp }
        Para1Value:=para1min.value;
        deltaPara1 := (para1max.value - para1min.value) / Para1mesh.value;
        for i:=0 to para1mesh.value do
        begin
           with MyMultiLayer do
           begin
             if Para1Combo.text='z' then begin z[idxLayer]:=1e-9*Para1Value end;
             if Para1Combo.text='b' then begin bn[idxLayer]:=1e-15*Para1Value end;
             if Para1Combo.text='bi' then begin bni[idxLayer]:=1e-15*Para1Value end;
             if Para1Combo.text='f' then begin f[idxLayer]:=Para1Value end;
             if Para1Combo.text='fi' then begin fi[idxLayer]:=Para1Value end;
             if Para1Combo.text='rho' then begin d[idxLayer]:=1e28*Para1Value end;
             if Para1Combo.text='M' then begin Aim[idxLayer]:=(mu0*muB*d[idxLayer])*Para1Value end;
             if Para1Combo.text='theta' then begin Theta[idxLayer]:=Para1Value*pi/180 end;
             if Para1Combo.text='phi' then begin Phi[idxLayer]:=Para1Value*pi/180 end;
             if Para1Combo.text='sigma' then begin sigma[idxLayer]:=1e-9*Para1Value end;
           end;
        MiseAjourPotentiels;
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
        MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
        diff:=difference(MyDataExp,MyDataCalc,MyExperimentalParameters);ecartBox.value:=diff;
        und.spect[ind].data[i,0,0].x:=para1value;
        und.spect[ind].data[i,0,0].z:=diff;
        para1Value:=para1value+deltaPara1;
        end;
        sendmessage(principalform.handle,wm_redessine,0,0);
     end;
end;

if (para2checkbox.checked=true)
then begin
     { effacement des modif qui ont pu etre faites par la procedure ci-dessus }
     MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
        ind:=und.addspectre('stabilityP2',Para2mesh.value+1,1,1);
        i:=0; while (MyMultiLayer.layerIdx[i]<>para2LayerNumber.value) and  (i<nbrlayersMax) do inc(i);
        if (i=nbrLayersMax)
        then MessageDlg('Layer does not exist!', mtInformation, [mbOk], 0)
        else begin
        idxLayer:=i;
        { on suppose qu'on dispose d'un tableau de data Rexp }
        Para2Value:=para2min.value;
        deltaPara2 := (para2max.value - para2min.value) / Para2mesh.value;
        for i:=0 to para2mesh.value do
        begin
           with MyMultiLayer do
           begin
             if Para2Combo.text='z' then begin z[idxLayer]:=1e-9*Para2Value end;
             if Para2Combo.text='b' then begin bn[idxLayer]:=1e-15*Para2Value end;
             if Para2Combo.text='bi' then begin bni[idxLayer]:=1e-15*Para2Value end;
             if Para2Combo.text='f' then begin f[idxLayer]:=Para2Value end;
             if Para2Combo.text='fi' then begin fi[idxLayer]:=Para2Value end;
             if Para2Combo.text='rho' then begin d[idxLayer]:=1e28*Para2Value end;
             if Para2Combo.text='M' then begin Aim[idxLayer]:=(mu0*muB*d[idxLayer])*Para2Value end;
             if Para2Combo.text='theta' then begin Theta[idxLayer]:=Para2Value*pi/180 end;
             if Para2Combo.text='phi' then begin Phi[idxLayer]:=Para2Value*pi/180 end;
             if Para2Combo.text='sigma' then begin sigma[idxLayer]:=1e-9*Para2Value end;
           end;
        MiseAjourPotentiels;
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
        MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
        diff:=difference(MyDataExp,MyDataCalc,MyExperimentalParameters);ecartBox.value:=diff;
        und.spect[ind].data[i,0,0].x:=para2value;
        und.spect[ind].data[i,0,0].z:=diff;
        para2Value:=para2value+deltaPara2;
        end;
        sendmessage(principalform.handle,wm_redessine,0,0);
     end;
end;

{ cas ou on veut faire un plot en 2 dimensions }
if (deuxDCheckBox.checked=true)
then begin
        ind:=deuxd.addspectre('Stability',Para1mesh.value+1,Para1mesh.value+1,1);
        i:=0; while (MyMultiLayer.layerIdx[i]<>para1LayerNumber.value) and (i<nbrlayersMax) do inc(i);
        if (i=nbrLayersMax)
        then MessageDlg('Layer does not exist!', mtInformation, [mbOk], 0)
        else begin
             idxLayer1:=i;
             i:=0; while (MyMultiLayer.layerIdx[i]<>para2LayerNumber.value) and (i<nbrlayersMax) do inc(i);
             if (i=nbrLayersMax)
             then MessageDlg('Layer does not exist!', mtInformation, [mbOk], 0)
             else begin
                  idxLayer2:=i;

{        zmax:=-1e30;zmin:=1e30; }
        { on suppose qu'on dispose d'un tableau de data Rexp }
        deltaPara1 := (para1max.value - para1min.value) / Para1mesh.value;
        deltaPara2 := (para2max.value - para2min.value) / Para2mesh.value;

     Para1Value:=para1min.value;
     begin
        for i:=0 to Para1mesh.value do
        begin
          para2Value:=para2min.value;
          for j:=0 to Para2mesh.value do
          begin
            with MyMultiLayer do
            begin
            if Para1Combo.text='z' then begin z[idxLayer1]:=1e-9*Para1Value end;
            if Para1Combo.text='b' then begin bn[idxLayer1]:=1e-15*Para1Value end;
            if Para1Combo.text='bi' then begin bni[idxLayer1]:=1e-15*Para1Value end;
            if Para1Combo.text='f' then begin f[idxLayer1]:=Para1Value end;
            if Para1Combo.text='fi' then begin fi[idxLayer1]:=Para1Value end;
            if Para1Combo.text='rho' then begin d[idxLayer1]:=1e28*Para1Value end;
            if Para1Combo.text='M' then begin Aim[idxLayer1]:=(mu0*muB*d[idxLayer1])*Para1Value end;
            if Para1Combo.text='theta' then begin Theta[idxLayer1]:=Para1Value*pi/180 end;
            if Para1Combo.text='phi' then begin Phi[idxLayer1]:=Para1Value*pi/180 end;
            if Para1Combo.text='sigma' then begin sigma[idxLayer1]:=1e-9*Para1Value end;
            { ===== }
            if Para2Combo.text='z' then begin z[idxLayer2]:=1e-9*Para2Value end;
            if Para2Combo.text='b' then begin bn[idxLayer2]:=1e-15*Para2Value end;
            if Para2Combo.text='bi' then begin bni[idxLayer2]:=1e-15*Para2Value end;
            if Para2Combo.text='f' then begin f[idxLayer2]:=Para2Value end;
            if Para2Combo.text='fi' then begin fi[idxLayer2]:=Para2Value end;
            if Para2Combo.text='rho' then begin d[idxLayer2]:=1e28*Para2Value end;
            if Para2Combo.text='M' then begin Aim[idxLayer2]:=(mu0*muB*d[idxLayer2])*Para2Value end;
            if Para2Combo.text='theta' then begin Theta[idxLayer2]:=Para2Value*pi/180 end;
            if Para2Combo.text='phi' then begin Phi[idxLayer2]:=Para2Value*pi/180 end;
            if Para2Combo.text='sigma' then begin sigma[idxLayer2]:=1e-9*Para2Value end;
            end;
            MiseAjourPotentiels;

            CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
            MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
            diff:=difference(MyDataExp,MyDataCalc,MyExperimentalParameters);ecartBox.value:=diff;
            deuxd.spect[ind].data[i,j,0].x:=para1value;
            deuxd.spect[ind].data[i,j,0].y:=para2value;
            deuxd.spect[ind].data[i,j,0].z:=diff;
            para2Value:=para2value+deltaPara2;
          end;
          para1Value:=para1value+deltaPara1;
        end;
     end;
                 end; { test2 if layer exists }
          end; { test1 if layer exists }
     sendmessage(principalform.handle,wm_redessine,0,0);
     end;

   StabilityPlotStatus.caption:='Idle';StabilityPlotStatus.update;
   PlayWave('The_stability_plot_is_ready');
end;

{ 04.02.03 : FO : il y avait un problème de cumul des arrondis quand les couches sont nombreuses }
{                 ajout du profil de rugosité                                   }
procedure TSimulReflecWindow.PlotProfile(var MyML:TMultiLayer;var MyEP:TExperimentalParameters);
var nbrLayers,i,j,zint,z1int,zcrt,Z0:integer;
    ind,indUP,indDO,indM,indPhi,indErf,indUPerf,indDOerf:integer;
    z,z1,zaux:double; { z1 est l'épaisseur qu'on utilise pour le milieu d'incidence et le substrat }
    SLD0,SLD1,SLDm1,SIG0,SIGm1,SLD0up,SLD1up,SLDm1up,SLD0do,SLD1do,SLDm1do,AngPhi:double;
    InSLflag:boolean; { flag pour le tracé du profil quand on a un super-réseau }
begin
   indUP:=-1;indDO:=-1;indM:=-1;

if not(MyML.MLsystem) { si ce n'est pas un superréseau  }
then begin
   nbrLayers:=MyML.nbrLayers;
 { détermination de l'épaisseur totale du système }
 { ainsi que de l'indice maximum et minimum}
   z:=0;
   for i:=0 to nbrLayers-1 do begin z:=z+MyML.z[i]*1e9; end;
   { pour le substrat et le milieu d'incidence on prend le quart de l'épaisseur totale }
   { on passe en angtroms }
   zint:=round(z*10);z1int:=zint div 2;
   ind:=und.addspectre('ProfileNP',zint+2*z1int+nbrLayers,1,1); { on calcule sytémaiquement le profil non polarisé }
   indErf:=und.addspectre('ProfileNPerf',zint+2*z1int+nbrLayers,1,1);
   if (MyEP.PolarisationType='polarised') or (MyEP.PolarisationType='with spin-flip')
   then begin indUP:=und.addspectre('ProfileUP',zint+2*z1int+nbrLayers,1,1);indDO:=und.addspectre('ProfileDO',zint+2*z1int+nbrLayers,1,1);
              indUPerf:=und.addspectre('ProfileUPerf',zint+2*z1int+nbrLayers,1,1);indDOerf:=und.addspectre('ProfileDOerf',zint+2*z1int+nbrLayers,1,1);
              indM:=und.addspectre('ProfileM',zint+2*z1int+nbrLayers,1,1);
              indPhi:=und.addspectre('ProfilePhi',zint+2*z1int+nbrLayers,1,1) end;
   { nota : le facteur '+nbrLayers' est la pour compenser les arrondis potentiels sur l'épaisseur au niveau de chaque couche }

  Zcrt:=-1;
  if MyEP.particles='neutrons'
  then begin SLD0:=MyML.d[0]*MyML.bn[0]*1e-28*1e15;SLD1:=MyML.d[1]*MyML.bn[1]*1e-28*1e15;
             SLD0up:=(MyML.d[0]*MyML.bn[0]-MyML.Aim[0]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLD1up:=(MyML.d[1]*MyML.bn[1]-MyML.Aim[1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
             SLD0do:=(MyML.d[0]*MyML.bn[0]+MyML.Aim[0]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLD1do:=(MyML.d[1]*MyML.bn[1]+MyML.Aim[1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
             AngPhi:=MyML.phi[0]*180/pi end
  else begin SLD0:=MyML.d[0]*MyML.f[0];SLD1:=MyML.d[1]*MyML.f[1] end;
  SIG0:=MyML.sigma[0]*1e10+0.01; { en angstroms + un epsilon pour eviter la singularité }
  for i:=0 to z1int-1 do { substrat }
    begin
    inc(Zcrt);
    if ind<>-1 then begin
                und.spect[ind].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[ind].data[zcrt,0,0].z:=SLD0;
                { tracé en tenant compte de la rugosité }
                und.spect[indErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indErf].data[zcrt,0,0].z:=SLD0+(SLD1-SLD0)/2*(1+erf((i-z1int)/SIG0));
                end;
    if indUP<>-1 then begin
                zaux:=zcrt/10-z1int/10;
                und.spect[indUP].data[zcrt,0,0].x:=zaux;und.spect[indDO].data[zcrt,0,0].x:=zaux;und.spect[indM].data[zcrt,0,0].x:=zaux;und.spect[indPhi].data[zcrt,0,0].x:=zaux;
                und.spect[indUP].data[zcrt,0,0].z:=SLD0up;und.spect[indDO].data[zcrt,0,0].z:=SLD0do;und.spect[indM].data[zcrt,0,0].z:=(SLD0up-SLD0do)/2;und.spect[indPhi].data[zcrt,0,0].z:=angPhi;
                { tracé en tenant compte de la rugosité }
                und.spect[indUPErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indUPErf].data[zcrt,0,0].z:=SLD0up+(SLD1up-SLD0up)/2*(1+erf((i-z1int)/SIG0));
                und.spect[indDOErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indDOErf].data[zcrt,0,0].z:=SLD0do+(SLD1do-SLD0do)/2*(1+erf((i-z1int)/SIG0));
                end;
    end;
  for j:=1 to nbrLayers-2 do
  begin
    if MyEP.particles='neutrons'
    then begin SLD0:=MyML.d[j]*MyML.bn[j]*1e-28*1e15;SLDm1:=MyML.d[j-1]*MyML.bn[j-1]*1e-28*1e15;SLD1:=MyML.d[j+1]*MyML.bn[j+1]*1e-28*1e15;
               SLD0up:=(MyML.d[j]*MyML.bn[j]-MyML.Aim[j]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLDm1up:=(MyML.d[j-1]*MyML.bn[j-1]-MyML.Aim[j-1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLD1up:=(MyML.d[j+1]*MyML.bn[j+1]-MyML.Aim[j+1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
               SLD0do:=(MyML.d[j]*MyML.bn[j]+MyML.Aim[j]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLDm1do:=(MyML.d[j-1]*MyML.bn[j-1]+MyML.Aim[j-1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLD1do:=(MyML.d[j+1]*MyML.bn[j+1]+MyML.Aim[j+1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
               AngPhi:=MyML.phi[j]*180/pi end
    else begin SLD0:=MyML.d[j]*MyML.f[j];SLDm1:=MyML.d[j-1]*MyML.f[j-1];SLD1:=MyML.d[j+1]*MyML.f[j+1] end;
    SIG0:=MyML.sigma[j]*1e10+0.01;SIGm1:=MyML.sigma[j-1]*1e10+0.01; { en angstroms }
    Z0:=round(MyML.z[j]*1e10)-1;
    for i:=0 to Z0 do
    begin
      inc(Zcrt);
      if ind<>-1 then begin
                und.spect[ind].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[ind].data[zcrt,0,0].z:=SLD0;
                { tracé en tenant compte de la rugosité }
                und.spect[indErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indErf].data[zcrt,0,0].z:=SLDm1+(SLD0-SLDm1)/2*(1+erf(i/SIGm1))+(SLD1-SLD0)/2*(1+erf((i-1-Z0)/SIG0));
                end;
      if indUP<>-1 then begin
                und.spect[indUP].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indUP].data[zcrt,0,0].z:=SLD0up;
                und.spect[indDO].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indDO].data[zcrt,0,0].z:=SLD0do;
                und.spect[indM].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indM].data[zcrt,0,0].z:=(SLD0up-SLD0do)/2;
                und.spect[indPhi].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indPhi].data[zcrt,0,0].z:=angPhi;
                { tracé en tenant compte de la rugosité }
                und.spect[indUPErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indUPErf].data[zcrt,0,0].z:=SLDm1Up+(SLD0up-SLDm1up)/2*(1+erf(i/SIGm1))+(SLD1up-SLD0up)/2*(1+erf((i-1-Z0)/SIG0));
                und.spect[indDOErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indDOErf].data[zcrt,0,0].z:=SLDm1Do+(SLD0do-SLDm1do)/2*(1+erf(i/SIGm1))+(SLD1do-SLD0do)/2*(1+erf((i-1-Z0)/SIG0));
                end;
    end;
  end;
  j:=nbrLayers-1;
  if MyEP.particles='neutrons'
  then begin SLD0:=MyML.d[j]*MyML.bn[j]*1e-28*1e15;SLDm1:=MyML.d[j-1]*MyML.bn[j-1]*1e-28*1e15;
             SLD0up:=(MyML.d[j]*MyML.bn[j]-MyML.Aim[j]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLDm1up:=(MyML.d[j-1]*MyML.bn[j-1]-MyML.Aim[j-1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
             SLD0do:=(MyML.d[j]*MyML.bn[j]+MyML.Aim[j]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLDm1do:=(MyML.d[j-1]*MyML.bn[j-1]+MyML.Aim[j-1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
             AngPhi:=MyML.phi[j]*180/pi end
  else begin SLD0:=MyML.d[j]*MyML.f[j];SLDm1:=MyML.d[j-1]*MyML.f[j-1] end;
{  SIG0:=MyML.sigma[j]*1e10+0.01;SIGm1:=MyML.sigma[j-1]*1e10+0.01; { en angstroms }
{  Z0:=round(MyMultiLayer.z[j]*1e10)-1; }

  for i:=0 to z1int-1 do { milieu d'incidence }
    begin
    inc(Zcrt);
    if ind<>-1 then begin
                und.spect[ind].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[ind].data[zcrt,0,0].z:=SLD0;
                { tracé en tenant compte de la rugosité }
                und.spect[indErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indErf].data[zcrt,0,0].z:=SLDm1+(SLD0-SLDm1)/2*(1+erf(i/SIGm1));
                end;
    if indUP<>-1 then begin
                und.spect[indUP].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indUP].data[zcrt,0,0].z:=SLD0up;
                und.spect[indDO].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indDO].data[zcrt,0,0].z:=SLD0do;
                und.spect[indM].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indM].data[zcrt,0,0].z:=(SLD0up-SLD0do)/2;
                und.spect[indPhi].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indPhi].data[zcrt,0,0].z:=angPhi;
                { tracé en tenant compte de la rugosité }
                und.spect[indUPErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indUPErf].data[zcrt,0,0].z:=SLDm1UP+(SLD0up-SLDm1up)/2*(1+erf(i/SIGm1));
                und.spect[indDOErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indDOErf].data[zcrt,0,0].z:=SLDm1DO+(SLD0do-SLDm1do)/2*(1+erf(i/SIGm1));
                end;
    end;
  { redimensionnement des spectres 1D ******* HORREUR !!!! ******* }
  { il faut utiliser la fonction de redimensionnement des spectres (qui n'existe pas encore) }
  setlength(und.spect[ind].data,zcrt-1,1,1);und.spect[ind].X:=zcrt-1;
  setlength(und.spect[indErf].data,zcrt-1,1,1);und.spect[indErf].X:=zcrt-1;
  if (MyEP.PolarisationType='polarised') or (MyEP.PolarisationType='with spin-flip')
  then begin
        setlength(und.spect[indUP].data,zcrt-1,1,1);und.spect[indUP].X:=zcrt-1;
        setlength(und.spect[indUPErf].data,zcrt-1,1,1);und.spect[indUPErf].X:=zcrt-1;
        setlength(und.spect[indDO].data,zcrt-1,1,1);und.spect[indDO].X:=zcrt-1;
        setlength(und.spect[indDoErf].data,zcrt-1,1,1);und.spect[indDOErf].X:=zcrt-1;
        setlength(und.spect[indM].data,zcrt-1,1,1);und.spect[indM].X:=zcrt-1;
        setlength(und.spect[indPhi].data,zcrt-1,1,1);und.spect[indPhi].X:=zcrt-1;
        end;
end

else  { cas d'un superréseau }
begin
   nbrLayers:=MyML.zML.length;
 { détermination de l'épaisseur totale du système }
 { ainsi que de l'indice maximum et minimum}
   z:=0;
   for i:=0 to nbrLayers-1 do begin z:=z+MyML.zML[i]*1e9; end;
   { pour le substrat et le milieu d'incidence on prend le quart de l'épaisseur totale }
   { on passe en angtroms }
   zint:=round(z*10);z1int:=zint div 2;
   ind:=und.addspectre('ProfileNP',zint+2*z1int+nbrLayers,1,1); { on calcule sytémaiquement le profil non polarisé }
   indErf:=und.addspectre('ProfileNPerf',zint+2*z1int+nbrLayers,1,1);
   if (MyEP.PolarisationType='polarised') or (MyEP.PolarisationType='with spin-flip')
   then begin indUP:=und.addspectre('ProfileUP',zint+2*z1int+nbrLayers,1,1);indDO:=und.addspectre('ProfileDO',zint+2*z1int+nbrLayers,1,1);
              indUPerf:=und.addspectre('ProfileUPerf',zint+2*z1int+nbrLayers,1,1);indDOerf:=und.addspectre('ProfileDOerf',zint+2*z1int+nbrLayers,1,1);
              indM:=und.addspectre('ProfileM',zint+2*z1int+nbrLayers,1,1);
              indPhi:=und.addspectre('ProfilePhi',zint+2*z1int+nbrLayers,1,1); end;
   { nota : le facteur '+nbrLayers' est la pour compenser les arrondis potentiels sur l'épaisseur au niveau de chaque couche }

  Zcrt:=-1;
  if MyEP.particles='neutrons'
  then begin SLD0:=MyML.dML[0]*MyML.bnML[0]*1e-28*1e15;SLD1:=MyML.dML[1]*MyML.bnML[1]*1e-28*1e15;
             SLD0up:=(MyML.dML[0]*MyML.bnML[0]-MyML.AimML[0]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLD1up:=(MyML.dML[1]*MyML.bnML[1]-MyML.AimML[1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
             SLD0do:=(MyML.dML[0]*MyML.bnML[0]+MyML.AimML[0]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLD1do:=(MyML.dML[1]*MyML.bnML[1]+MyML.AimML[1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
             AngPhi:=MyML.phi[0]*180/pi end
  else begin SLD0:=MyML.dML[0]*MyML.fML[0];SLD1:=MyML.dML[1]*MyML.fML[1] end;
  SIG0:=MyML.sigmaML[0]*1e10+0.01; { en angstroms + un epsilon pour eviter la singularité }
  for i:=0 to z1int-1 do { substrat }
    begin
    inc(Zcrt);
    if ind<>-1 then begin
                und.spect[ind].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[ind].data[zcrt,0,0].z:=SLD0;
                { tracé en tenant compte de la rugosité }
                und.spect[indErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indErf].data[zcrt,0,0].z:=SLD0+(SLD1-SLD0)/2*(1+erf((i-z1int)/SIG0));
                end;
    if indUP<>-1 then begin
                und.spect[indUP].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indDO].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indM].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indPhi].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indUP].data[zcrt,0,0].z:=SLD0up;und.spect[indDO].data[zcrt,0,0].z:=SLD0do;und.spect[indM].data[zcrt,0,0].z:=(SLD0UP-SLD0do)/2;
                und.spect[indPhi].data[zcrt,0,0].z:=AngPhi;
                { tracé en tenant compte de la rugosité }
                und.spect[indUPErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indUPErf].data[zcrt,0,0].z:=SLD0up+(SLD1up-SLD0up)/2*(1+erf((i-z1int)/SIG0));
                und.spect[indDOErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indDOErf].data[zcrt,0,0].z:=SLD0do+(SLD1do-SLD0do)/2*(1+erf((i-z1int)/SIG0));
                end;
    end;
  for j:=1 to nbrLayers-2 do
  begin
    if MyEP.particles='neutrons'
    then begin SLD0:=MyML.dML[j]*MyML.bnML[j]*1e-28*1e15;SLDm1:=MyML.dML[j-1]*MyML.bnML[j-1]*1e-28*1e15;SLD1:=MyML.dML[j+1]*MyML.bnML[j+1]*1e-28*1e15;
               SLD0up:=(MyML.dML[j]*MyML.bnML[j]-MyML.AimML[j]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLDm1up:=(MyML.dML[j-1]*MyML.bnML[j-1]-MyML.AimML[j-1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLD1up:=(MyML.dML[j+1]*MyML.bnML[j+1]-MyML.AimML[j+1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
               SLD0do:=(MyML.dML[j]*MyML.bnML[j]+MyML.AimML[j]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLDm1do:=(MyML.dML[j-1]*MyML.bnML[j-1]+MyML.AimML[j-1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLD1do:=(MyML.dML[j+1]*MyML.bnML[j+1]+MyML.AimML[j+1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
               AngPhi:=MyML.phiML[j]*180/pi end
    else begin SLD0:=MyML.dML[j]*MyML.fML[j];SLDm1:=MyML.dML[j-1]*MyML.fML[j-1];SLD1:=MyML.dML[j+1]*MyML.fML[j+1] end;
    SIG0:=MyML.sigmaML[j]*1e10+0.01;SIGm1:=MyML.sigmaML[j-1]*1e10+0.01; { en angstroms }
    Z0:=round(MyML.zML[j]*1e10)-1;
    for i:=0 to Z0 do
    begin
      inc(Zcrt);
      if ind<>-1 then begin
                und.spect[ind].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[ind].data[zcrt,0,0].z:=SLD0;
                { tracé en tenant compte de la rugosité }
                und.spect[indErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indErf].data[zcrt,0,0].z:=SLDm1+(SLD0-SLDm1)/2*(1+erf(i/SIGm1))+(SLD1-SLD0)/2*(1+erf((i-1-Z0)/SIG0));
                end;
      if indUP<>-1 then begin
                und.spect[indUP].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indUP].data[zcrt,0,0].z:=SLD0up;
                und.spect[indDO].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indDO].data[zcrt,0,0].z:=SLD0do;
                und.spect[indM].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indM].data[zcrt,0,0].z:=(SLD0up-SLD0do)/2;
                und.spect[indPhi].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indPhi].data[zcrt,0,0].z:=AngPhi;
                { tracé en tenant compte de la rugosité }
                und.spect[indUPErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indUPErf].data[zcrt,0,0].z:=SLDm1Up+(SLD0up-SLDm1up)/2*(1+erf(i/SIGm1))+(SLD1up-SLD0up)/2*(1+erf((i-1-Z0)/SIG0));
                und.spect[indDOErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indDOErf].data[zcrt,0,0].z:=SLDm1Do+(SLD0do-SLDm1do)/2*(1+erf(i/SIGm1))+(SLD1do-SLD0do)/2*(1+erf((i-1-Z0)/SIG0));
                end;
    end;
  end;
  j:=nbrLayers-1;
  if MyEP.particles='neutrons'
  then begin SLD0:=MyML.dML[j]*MyML.bnML[j]*1e-28*1e15;SLDm1:=MyML.dML[j-1]*MyML.bnML[j-1]*1e-28*1e15;
             SLD0up:=(MyML.dML[j]*MyML.bnML[j]-MyML.AimML[j]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLDm1up:=(MyML.dML[j-1]*MyML.bnML[j-1]-MyML.AimML[j-1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
             SLD0do:=(MyML.dML[j]*MyML.bnML[j]+MyML.AimML[j]*mun*mn/(2*Pi*hb2))*1e-28*1e15;SLDm1do:=(MyML.dML[j-1]*MyML.bnML[j-1]+MyML.AimML[j-1]*mun*mn/(2*Pi*hb2))*1e-28*1e15;
             AngPhi:=MyML.phiML[j]*180/pi end
  else begin SLD0:=MyML.dML[j]*MyML.fML[j];SLDm1:=MyML.dML[j-1]*MyML.fML[j-1] end;
{  SIG0:=MyML.sigma[j]*1e10+0.01;SIGm1:=MyML.sigma[j-1]*1e10+0.01; { en angstroms }
{  Z0:=round(MyMultiLayer.z[j]*1e10)-1; }

  for i:=0 to z1int-1 do { milieu d'incidence }
    begin
    inc(Zcrt);
    if ind<>-1 then begin
                und.spect[ind].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[ind].data[zcrt,0,0].z:=SLD0;
                { tracé en tenant compte de la rugosité }
                und.spect[indErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indErf].data[zcrt,0,0].z:=SLDm1+(SLD0-SLDm1)/2*(1+erf(i/SIGm1));
                end;
    if indUP<>-1 then begin
                und.spect[indUP].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indUP].data[zcrt,0,0].z:=SLD0up;
                und.spect[indDO].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indDO].data[zcrt,0,0].z:=SLD0do;
                und.spect[indM].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indDO].data[zcrt,0,0].z:=(SLD0up-SLD0do)/2;
                und.spect[indPhi].data[zcrt,0,0].x:=zcrt/10-z1int/10;und.spect[indPhi].data[zcrt,0,0].z:=AngPhi;
                { tracé en tenant compte de la rugosité }
                und.spect[indUPErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indUPErf].data[zcrt,0,0].z:=SLDm1UP+(SLD0up-SLDm1up)/2*(1+erf(i/SIGm1));
                und.spect[indDOErf].data[zcrt,0,0].x:=zcrt/10-z1int/10;
                und.spect[indDOErf].data[zcrt,0,0].z:=SLDm1DO+(SLD0do-SLDm1do)/2*(1+erf(i/SIGm1));
                end;
    end;
  { redimensionnement des spectres 1D ******* HORREUR !!!! ******* }
  { il faut utiliser la fonction de redimensionnement des spectres (qui n'existe pas encore) }
  setlength(und.spect[ind].data,zcrt-1,1,1);und.spect[ind].X:=zcrt-1;
  setlength(und.spect[indErf].data,zcrt-1,1,1);und.spect[indErf].X:=zcrt-1;
  if (MyEP.PolarisationType='polarised') or (MyEP.PolarisationType='with spin-flip')
  then begin
        setlength(und.spect[indUP].data,zcrt-1,1,1);und.spect[indUP].X:=zcrt-1;
        setlength(und.spect[indUPErf].data,zcrt-1,1,1);und.spect[indUPErf].X:=zcrt-1;
        setlength(und.spect[indDO].data,zcrt-1,1,1);und.spect[indDO].X:=zcrt-1;
        setlength(und.spect[indDoErf].data,zcrt-1,1,1);und.spect[indDOErf].X:=zcrt-1;
        setlength(und.spect[indM].data,zcrt-1,1,1);und.spect[indM].X:=zcrt-1;
        setlength(und.spect[indPhi].data,zcrt-1,1,1);und.spect[indPhi].X:=zcrt-1;
        end;
end;


end;

procedure TSimulReflecWindow.principalformPlotteprofile1Click(Sender: TObject);
begin
   plotProfile(MyMultilayer,MyExperimentalParameters);
end;

procedure TSimulReflecWindow.SLDProfiles1Click(Sender: TObject);
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   plotProfile(MyMultilayer,MyExperimentalParameters);
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

{ creation d'une courbe lambda spectrum représentant la distribution en lambda }
procedure TSimulReflecWindow.lambda1Click(Sender: TObject);
var i,ind:integer;
    nbPts:integer;
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   nbPts:=MyExperimentalParameters.lambdaSpectrum.length;
   ind:=und.addspectre('lambda',nbPts,1,1); { on calcule sytémaiquement le profil non polarisé }
   for i:=0 to nbPts-1 do
   begin
     und.spect[ind].data[i,0,0].x:=MyExperimentalParameters.lambdaSpectrum[i]*1e9;
     und.spect[ind].data[i,0,0].z:=MyExperimentalParameters.lambdaIntensity[i];
   end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

{ creation d'une courbe theta spectrum représentant la distribution en theta in }
procedure TSimulReflecWindow.theta1Click(Sender: TObject);
var i,ind:integer;
    nbPts:integer;
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   nbPts:=MyExperimentalParameters.thetaSpectrum.length;
   ind:=und.addspectre('thetaIn',nbPts,1,1); { on calcule sytémaiquement le profil non polarisé }
   for i:=0 to nbPts-1 do
   begin
     und.spect[ind].data[i,0,0].x:=MyExperimentalParameters.thetaSpectrum[i]*180/pi;
     und.spect[ind].data[i,0,0].z:=MyExperimentalParameters.thetaIntensity[i];
   end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

{ creation d'une courbe theta spectrum représentant la distribution en theta in }
{ plot des QzSpectrum (resolution vectors)                                      }
procedure TSimulReflecWindow.QzIn1Click(Sender: TObject);
var i,j:integer;
    nbPts:integer;
    ind:array[1..10] of integer; { tableau des indices des courbes QzSpectrum }
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   nbPts:=MyDataCalc.QzIntensity.length;
   for i:=1 to nbPts do ind[i]:=und.addspectre('QzIn'+IntToStr(i),MyDataCalc.QzSpectrum[0].length,1,1);
   for i:=1 to nbPts do
   begin
     for j:=0 to MyDataCalc.QzSpectrum[i].length-1 do
     begin
        und.spect[ind[i]].data[j,0,0].x:=j;
        und.spect[ind[i]].data[j,0,0].z:=MyDataCalc.QzSpectrum[i-1].values[j]*1e-9;
     end;
   end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;


{ tracé de la function d'onde en fonction de la profondeur dans la couche       }
{ INPUTs : sur le formulaire : dimension (1D or 2D), thetaI min, max, step      }
{ OUTPUT : tracé du module et de la phase sur le graph1D                        }
{ conventions : z du substrat vers le vide                                      }
{ premiere couche = substrat                                                    }
{ fonctionne pour le dioptre                                                    }
{ on recupere les amplitudes T+(a+1) et R+(a+1) à l'interface (a+1)             }
procedure TSimulReflecWindow.WaveFunction1Click(Sender: TObject);
begin
   WFcalcStatus.caption:='Calculation running';WFcalcStatus.update;
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

{ demande d'un tracé à une dimensions  }
   if WFdimension.itemIndex=0
   then begin
          if (MyExperimentalParameters.PolarisationType='non polarised')
          then CalculateWaveFunction1D('NP',MyMultiLayer,MyExperimentalParameters);
          if (MyExperimentalParameters.PolarisationType='polarised')
          then begin
                CalculateWaveFunction1D('UP',MyMultiLayer,MyExperimentalParameters);
                CalculateWaveFunction1D('DO',MyMultiLayer,MyExperimentalParameters); end;
        end;
{ demande d'un tracé à deux dimensions  }
   if WFdimension.itemIndex=1
   then begin
          if (MyExperimentalParameters.PolarisationType='non polarised')
          then CalculateWaveFunction2D(MyDataCalc,'NP',MyMultiLayer,MyExperimentalParameters);
          if (MyExperimentalParameters.PolarisationType='polarised')
          then begin
                CalculateWaveFunction2D(MyDataCalc,'UP',MyMultiLayer,MyExperimentalParameters);
                CalculateWaveFunction2D(MyDataCalc,'DO',MyMultiLayer,MyExperimentalParameters); end;
        end;
   WFcalcStatus.caption:='Idle';WFcalcStatus.update;
   { rafraichissement du graph1D}
   sendmessage(principalform.handle,wm_redessine,0,0);

   { TEMPORAIRE }
   if (MyExperimentalParameters.PolarisationType='with spin-flip')
   or (MyExperimentalParameters.PolarisationType='with SF high field')
   then MessageDlg('Not implemented yet for spin-flip', mtInformation, [mbOk], 0);
end;

{ ecriture des paramètres d'une ML dans le grille MultiLayergrid                }
{ DANGER : cette procedure suppose que la grille existante contient autant de lignes que MyML }
{ Ce n'est pas vrai dans le cas des profils                                     }
{ c'est aussi valable dans les cas ou la couche sauveagrdée n'a pas le meme     }
{ nombre de lignes que la couche en cours                                       }
procedure TSimulReflecWindow.MiseAjourMultiLayerGrid(var MyML:TMultiLayer;var MyGrid:TAdvStringGrid);
var i,indexLayer:integer;
begin
   { il faut tenir compte des couches desactivées (avec Y/N) }
   i:=0;indexLayer:=1;
   while i<=(MyML.NbrLayers-1) do
   begin
      with MyGrid do
      begin
          if Uppercase(Cells[ColYN,indexLayer])='Y'
          then with MyML do
               begin
                  Cells[ColDescription,indexLayer]:=Description[i];
                  Cells[ColEpaisseur,indexLayer]:=FloatToStr(z[i]*1E9);
                  Cells[ColDensity,indexLayer]:=FloatToStr(d[i]*1e-28);
                  if MyExperimentalParameters.Particles='xrays' then
                  begin Cells[ColF,indexLayer]:=FloatToStr(f[i]);
                        Cells[ColFi,indexLayer]:=FloatToStr(fi[i])  end;
                  if MyExperimentalParameters.Particles='neutrons' then
                  begin Cells[ColB,indexLayer]:=FloatToStr(bn[i]*1e15);
                        Cells[ColBi,indexLayer]:=FloatToStr(bni[i]*1e15);
                        if d[i]<>0 then Cells[ColM,indexLayer]:=FloatToStr(Aim[i]/(mu0*muB*d[i])) end;
                  Cells[ColTheta,indexLayer]:=FloatToStr(theta[i]*180/pi);
                  Cells[ColPhi,indexLayer]:=FloatToStr(phi[i]*180/pi);
                  Cells[ColSigma,indexLayer]:=FloatToStr(sigma[i]*1e9);
                  Cells[ColXsi,indexLayer]:=FloatToStr(xsi[i]*1e9);
                  Cells[Colh,indexLayer]:=FloatToStr(exph[i]);
                  { les incdices Y/N }
                  if zYN[i]=-1 then Cells[ColEpaisseurYN,indexLayer]:='N' else if (ord(zCorr[i])>=65) or (ord(zCorr[i])<=90) then Cells[ColEpaisseurYN,indexLayer]:=zCorr[i] else Cells[ColEpaisseurYN,indexLayer]:=FloatToStr(zStep[i]);
                  if dYN[i]=-1 then Cells[ColDensityYN,indexLayer]:='N' else if (ord(dCorr[i])>=65) or (ord(dCorr[i])<=90) then Cells[ColDensityYN,indexLayer]:=dCorr[i] else Cells[ColDensityYN,indexLayer]:=FloatToStr(dStep[i]);
                  if MyExperimentalParameters.Particles='xrays' then
                  begin if fYN[i]=-1 then Cells[ColFYN,indexLayer]:='N' else if (ord(fCorr[i])>=65) or (ord(fCorr[i])<=90) then Cells[ColFYN,indexLayer]:=fCorr[i] else Cells[ColFYN,indexLayer]:=FloatToStr(fStep[i]);
                        if fiYN[i]=-1 then Cells[ColFiYN,indexLayer]:='N' else if (ord(fiCorr[i])>=65) or (ord(fiCorr[i])<=90) then Cells[ColFiYN,indexLayer]:=fiCorr[i] else Cells[ColFiYN,indexLayer]:=FloatToStr(fiStep[i]); end;
                  if MyExperimentalParameters.Particles='neutrons' then
                  begin if bYN[i]=-1 then Cells[ColbYN,indexLayer]:='N' else if (ord(bCorr[i])>=65) or (ord(bCorr[i])<=90) then Cells[ColbYN,indexLayer]:=bCorr[i] else Cells[ColbYN,indexLayer]:=FloatToStr(bStep[i]);
                        if biYN[i]=-1 then Cells[ColbiYN,indexLayer]:='N' else if (ord(biCorr[i])>=65) or (ord(biCorr[i])<=90) then Cells[ColbiYN,indexLayer]:=biCorr[i] else Cells[ColbiYN,indexLayer]:=FloatToStr(biStep[i]);
                        if MYN[i]=-1 then Cells[ColMYN,indexLayer]:='N' else if (ord(MCorr[i])>=65) or (ord(MCorr[i])<=90) then Cells[ColMYN,indexLayer]:=MCorr[i] else Cells[ColMYN,indexLayer]:=FloatToStr(AimStep[i]);
                        if thetaYN[i]=-1 then Cells[ColThetaYN,indexLayer]:='N' else if (ord(ThetaCorr[i])>=65) or (ord(ThetaCorr[i])<=90) then Cells[ColThetaYN,indexLayer]:=ThetaCorr[i] else Cells[ColThetaYN,indexLayer]:=FloatToStr(ThetaStep[i]);
                        if phiYN[i]=-1 then Cells[ColPhiYN,indexLayer]:='N' else if (ord(PhiCorr[i])>=65) or (ord(PhiCorr[i])<=90) then Cells[ColPhiYN,indexLayer]:=PhiCorr[i] else Cells[ColPhiYN,indexLayer]:=FloatToStr(PhiStep[i]);
                        if sigYN[i]=-1 then Cells[ColSigYN,indexLayer]:='N' else if (ord(SigmaCorr[i])>=65) or (ord(SigmaCorr[i])<=90) then Cells[ColSigYN,indexLayer]:=SigmaCorr[i] else Cells[ColSigYN,indexLayer]:=FloatToStr(SigmaStep[i]); end;
                  inc(i);
               end;
          inc(indexLayer);
      end;
   end;
end;

{ ecriture des paramètres d'une ML dans le grille MultiLayergrid                }
procedure TSimulReflecWindow.UpLoadMultiLayerGrid(var MyML:TMultiLayer;var MyGrid:TAdvStringGrid);
var i,indexLayer:integer;
begin
   i:=0;indexLayer:=1;
   { on fait un clear de la grille }
   MyGrid.ClearNormalCells;
   MyGrid.RowCount:=MyML.nbrLayers+2; { ACHTUNG +2 parce qu'il y a une message Trial version qui ecrase la denrière ligne des tableau }
   while i<=(MyML.NbrLayers-1) do
   begin
      with MyGrid do
      begin
         with MyML do
           begin
               Cells[ColYN,indexLayer]:='Y';
               Cells[ColDescription,indexLayer]:=Description[i];
               Cells[ColEpaisseur,indexLayer]:=FloatToStr(z[i]*1E9);
               Cells[ColDensity,indexLayer]:=FloatToStr(d[i]*1e-28);
               if MyExperimentalParameters.Particles='xrays' then
               begin Cells[ColF,indexLayer]:=FloatToStr(f[i]);
                        Cells[ColFi,indexLayer]:=FloatToStr(fi[i])  end;
               if MyExperimentalParameters.Particles='neutrons' then
               begin Cells[ColB,indexLayer]:=FloatToStr(bn[i]*1e15);
                     Cells[ColBi,indexLayer]:=FloatToStr(bni[i]*1e15);
                     if d[i]<>0 then Cells[ColM,indexLayer]:=FloatToStr(Aim[i]/(mu0*muB*d[i])) end;
               Cells[ColTheta,indexLayer]:=FloatToStr(theta[i]*180/pi);
               Cells[ColPhi,indexLayer]:=FloatToStr(phi[i]*180/pi);
               Cells[ColSigma,indexLayer]:=FloatToStr(sigma[i]*1e9);
               Cells[ColXsi,indexLayer]:=FloatToStr(xsi[i]*1e9);
               Cells[Colh,indexLayer]:=FloatToStr(exph[i]);
               { les incdices Y/N }
                  if zYN[i]=-1
                  then Cells[ColEpaisseurYN,indexLayer]:='N'
                  else if (ord(zCorr[i])>=65) and (ord(zCorr[i])<=90)
                       then Cells[ColEpaisseurYN,indexLayer]:=zCorr[i]
                       else Cells[ColEpaisseurYN,indexLayer]:=FloatToStr(zStep[i]*1e9);
                  if dYN[i]=-1 then Cells[ColDensityYN,indexLayer]:='N' else if (ord(dCorr[i])>=65) and (ord(dCorr[i])<=90) then Cells[ColDensityYN,indexLayer]:=dCorr[i] else Cells[ColDensityYN,indexLayer]:=FloatToStr(dStep[i]*1e-28);
                  if MyExperimentalParameters.Particles='xrays' then
                  begin if fYN[i]=-1 then Cells[ColFYN,indexLayer]:='N' else if (ord(fCorr[i])>=65) and (ord(fCorr[i])<=90) then Cells[ColFYN,indexLayer]:=fCorr[i] else Cells[ColFYN,indexLayer]:=FloatToStr(fStep[i]);
                        if fiYN[i]=-1 then Cells[ColFiYN,indexLayer]:='N' else if (ord(fiCorr[i])>=65) and (ord(fiCorr[i])<=90) then Cells[ColFiYN,indexLayer]:=fiCorr[i] else Cells[ColFiYN,indexLayer]:=FloatToStr(fiStep[i]); end;
                  if MyExperimentalParameters.Particles='neutrons' then
                  begin if bYN[i]=-1 then Cells[ColbYN,indexLayer]:='N' else if (ord(bCorr[i])>=65) and (ord(bCorr[i])<=90) then Cells[ColbYN,indexLayer]:=bCorr[i] else Cells[ColbYN,indexLayer]:=FloatToStr(bStep[i]*1e15);
                        if biYN[i]=-1 then Cells[ColbiYN,indexLayer]:='N' else if (ord(biCorr[i])>=65) and (ord(biCorr[i])<=90) then Cells[ColbiYN,indexLayer]:=biCorr[i] else Cells[ColbiYN,indexLayer]:=FloatToStr(biStep[i]*1e15);
                        if MYN[i]=-1 then Cells[ColMYN,indexLayer]:='N' else if (ord(MCorr[i])>=65) and (ord(MCorr[i])<=90) then Cells[ColMYN,indexLayer]:=MCorr[i] else Cells[ColMYN,indexLayer]:=FloatToStr(AimStep[i]/(mu0*muB*d[i]));
                        if thetaYN[i]=-1 then Cells[ColThetaYN,indexLayer]:='N' else if (ord(ThetaCorr[i])>=65) and (ord(ThetaCorr[i])<=90) then Cells[ColThetaYN,indexLayer]:=ThetaCorr[i] else Cells[ColThetaYN,indexLayer]:=FloatToStr(ThetaStep[i]*180/pi);
                        if phiYN[i]=-1 then Cells[ColPhiYN,indexLayer]:='N' else if (ord(PhiCorr[i])>=65) and (ord(PhiCorr[i])<=90) then Cells[ColPhiYN,indexLayer]:=PhiCorr[i] else Cells[ColPhiYN,indexLayer]:=FloatToStr(PhiStep[i]*180/pi);
                        if sigYN[i]=-1 then Cells[ColSigYN,indexLayer]:='N' else if (ord(SigmaCorr[i])>=65) and (ord(SigmaCorr[i])<=90) then Cells[ColSigYN,indexLayer]:=SigmaCorr[i] else Cells[ColSigYN,indexLayer]:=FloatToStr(SigmaStep[i]*1e9); end;
               Ints[ColProfile,indexLayer]:=Profile[i];
               inc(i);
            end;
          inc(indexLayer);
      end;
   end;
end;

{ sauvagarde d'un système multicouche }
procedure TSimulReflecWindow.JvMultilineButton2Click(Sender: TObject);
begin
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyMultiLayerUndo.clone(MyMultiLayer);
end;

{ rechargement d'un système multicouche }
procedure TSimulReflecWindow.JvMultilineButton3Click(Sender: TObject);
begin
   MyMultiLayer.clone(MyMultiLayerUndo);
   MiseAjourMultiLayerGrid(MyMultiLayer,MultiLayerGrid);
end;

{ génération d'un profil }
procedure TSimulReflecWindow.JvMultilineButton1Click(Sender: TObject);
var i,j,k:integer;
    NrOfLayers,CrtNbrLayers,NrSL:integer; { nombre de couche dans le système de départ } { nombre de couche du nouveau système }
    MLaux:TMultiLayer;
    pa,paSlope:double;
    profil:array[0..20] of double; { profil temporaire }
begin
   MLAux:=TMultiLayer.create;
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   { mise a jour de la variable des profils a partir de la grille }
   MyProfiles.update(ProfilesGrid);
   { backup de la Multicouche si on ne lui a pas encore fait de profiling }
   If MyMultilayer.profiled=false
   then MyMultiLayerBeforeProfiling.clone(MyMultiLayer) { on sauveagrde la ML source }
   else if (MyMultiLayerBeforeProfiling.nbrLayers<>0) then MyMultiLayer.clone(MyMultiLayerBeforeProfiling); { sinon on reveient a la ML originale }
   MyMultilayer.profiled:=true;
   FlagProfiling.caption:='Profiled ML';
   MLAux.Clone(MyMultiLayer);
   { mise a jour de MyMultiLayer }
   { update des vecteurs z,b,d,V }
   { determination du nombre de lignes dans le tableau }
   With MyMultiLayer do
   begin
     z.size(nbrLayersMax,false);d.size(nbrLayersMax,false);
     bn.size(nbrLayersMax,false);bni.size(nbrLayersMax,false);
     f.size(nbrLayersMax,false);fi.size(nbrLayersMax,false);
     Aim.size(nbrLayersMax,false);theta.size(nbrLayersMax,false);phi.size(nbrLayersMax,false);
     BeffMag.size(nbrLayersMax,false);BeffTheta.size(nbrLayersMax,false);BeffPhi.size(nbrLayersMax,false);
     V.size(nbrLayersMax,false);Vi.size(nbrLayersMax,false);
     Vup.size(nbrLayersMax,false);Vdo.size(nbrLayersMax,false);
     sigma.size(nbrLayersMax,false);xsi.size(nbrLayersMax,false);exph.size(nbrLayersMax,false);
   end;

   NrOfLayers:=MLaux.nbrLayers;
   i:=0;CrtNbrLayers:=0;  { nbrMLcrt:=0; }
   while (i<NrOfLayers) do
   begin
     { traitement du cas des profils                                 }
     { la couche que l'on vient de lire appartient-elle a un profil? }
     if (i+1) in MyProfiles.ProfiledLayers
     then begin
          { quel est l'indice du profil decrivant cette couche ? }
          { layer nbr se refere à l'indice de la couche dans le tableau excel }
          j:=1; while (MyProfiles.LayerNr[j]<>(i+1)) do inc(j);
          { on crée une serie de couches supplémentaires NbrPoints }
          { avec les parametres donnés par le tableau Excel }
          { ne pas oublier le parametre que l'on veut fitter }
          for k:=CrtNbrLayers to CrtNbrLayers+MyProfiles.NrOfSubLayers[j]-1 do
          begin
             { division des épaisseurs }
             MyMultiLayer.description[k]:=MLAux.description[CrtNbrLayers];
             MyMultiLayer.z[k]:=MLAux.z[CrtNbrLayers]/MyProfiles.NrOfSubLayers[j];
             MyMultiLayer.d[k]:=MLAux.d[CrtNbrLayers];
             MyMultiLayer.sigma[k]:=MLAux.sigma[CrtNbrLayers];
             MyMultiLayer.xsi[k]:=MLAux.xsi[CrtNbrLayers];
             MyMultiLayer.exph[k]:=MLAux.exph[CrtNbrLayers];
             MyMultiLayer.bn[k]:=MLAux.bn[CrtNbrLayers];MyMultiLayer.bni[k]:=MLAux.bni[CrtNbrLayers];
             MyMultiLayer.Aim[k]:=MLAux.Aim[CrtNbrLayers];
             MyMultiLayer.theta[k]:=MLAux.theta[CrtNbrLayers];
             MyMultiLayer.phi[k]:=MLAux.phi[CrtNbrLayers];
             MyMultiLayer.f[k]:=MLAux.f[CrtNbrLayers];MyMultiLayer.fi[k]:=MLAux.fi[CrtNbrLayers];
             { informations sur le profil }
             MyMultiLayer.Profile[k]:=j; { numéro du profil auquel est attachée cette couche }
             { activation de la couche }
             MyMultiLayer.zYN[k]:=MLAux.zYN[CrtNbrLayers];
             MyMultiLayer.dYN[k]:=MLAux.dYN[CrtNbrLayers];
             MyMultiLayer.sigYN[k]:=MLAux.sigYN[CrtNbrLayers];
             MyMultiLayer.bYN[k]:=MLAux.bYN[CrtNbrLayers];MyMultiLayer.biYN[k]:=MLAux.biYN[CrtNbrLayers];
             MyMultiLayer.MYN[k]:=MLAux.MYN[CrtNbrLayers];MyMultiLayer.thetaYN[k]:=MLAux.thetaYN[CrtNbrLayers];MyMultiLayer.phiYN[k]:=MLAux.phiYN[CrtNbrLayers];
             MyMultiLayer.fYN[k]:=MLAux.fYN[CrtNbrLayers];MyMultiLayer.fiYN[k]:=MLAux.fiYN[CrtNbrLayers];
             { steps de fit  }
             MyMultiLayer.zStep[k]:=MLAux.zStep[CrtNbrLayers];
             MyMultiLayer.dStep[k]:=MLAux.dStep[CrtNbrLayers];
             MyMultiLayer.sigmaStep[k]:=MLAux.sigmaStep[CrtNbrLayers];
             MyMultiLayer.bStep[k]:=MLAux.bStep[CrtNbrLayers];MyMultiLayer.biStep[k]:=MLAux.biStep[CrtNbrLayers];
             MyMultiLayer.AimStep[k]:=MLAux.AimStep[CrtNbrLayers];MyMultiLayer.thetaStep[k]:=MLAux.thetaStep[CrtNbrLayers];MyMultiLayer.phiStep[k]:=MLAux.phiStep[CrtNbrLayers];
             MyMultiLayer.fStep[k]:=MLAux.fStep[CrtNbrLayers];MyMultiLayer.fiStep[k]:=MLAux.fiStep[CrtNbrLayers];
             { copie des corrélations }
             MyMultiLayer.zCorr[k]:=MLAux.zCorr[CrtNbrLayers];
             MyMultiLayer.dCorr[k]:=MLAux.dCorr[CrtNbrLayers];
             MyMultiLayer.sigmaCorr[k]:=MLAux.sigmaCorr[CrtNbrLayers];
             MyMultiLayer.bCorr[k]:=MLAux.bCorr[CrtNbrLayers];MyMultiLayer.biCorr[k]:=MLAux.biCorr[CrtNbrLayers];
             MyMultiLayer.MCorr[k]:=MLAux.MCorr[CrtNbrLayers];MyMultiLayer.thetaCorr[k]:=MLAux.thetaCorr[CrtNbrLayers];MyMultiLayer.phiCorr[k]:=MLAux.phiCorr[CrtNbrLayers];
             MyMultiLayer.fCorr[k]:=MLAux.fCorr[CrtNbrLayers];MyMultiLayer.fiCorr[k]:=MLAux.fiCorr[CrtNbrLayers];
            end;
            { calcul du profil que l'on souhaite utiliser }
            { dans le cas smooth, on initialise a lineaire aussi; (pour le moment?) }
            NrSL:=MyProfiles.NrOfSubLayers[j]-1; { nombre de sous couche du dans leprofil }
            if (MyProfiles.ProfileType[j]='linear') or (MyProfiles.ProfileType[j]='smooth')
            then begin
                   pa:=MyProfiles.bottom[j];paSlope:=(MyProfiles.topp[j]-MyProfiles.bottom[j])/(MyProfiles.NrOfSubLayers[j]);
                   for k:=0 to NrSL do begin Profil[k]:=pa+paSlope*(k+0.5) end;
                 end;
            { quel est le parametre a faire varier ? }
            { creation du profil proprement dit }
            With MyMultilayer do
            begin
              if MyProfiles.parameter[j]='rho' then
                for k:=0 to NrSL do begin d[CrtNbrLayers+k]:=Profil[k]*1e28;dYN[CrtNbrLayers+k]:=0 end;
              if MyProfiles.parameter[j]='bn' then
                for k:=0 to NrSL do begin bn[CrtNbrLayers+k]:=Profil[k]*1e-15;bYN[CrtNbrLayers+k]:=0 end;
              if MyProfiles.parameter[j]='bni' then
                for k:=0 to NrSL do begin bni[CrtNbrLayers+k]:=Profil[k]*1e-15;biYN[CrtNbrLayers+k]:=0 end;
              if MyProfiles.parameter[j]='f' then
                for k:=0 to NrSL do begin f[CrtNbrLayers+k]:=Profil[k];fYN[CrtNbrLayers+k]:=0 end;
              if MyProfiles.parameter[j]='fi' then
                for k:=0 to NrSL do begin fi[CrtNbrLayers+k]:=Profil[k];fiYN[CrtNbrLayers+k]:=0 end;
              if MyProfiles.parameter[j]='M' then
{                for k:=0 to Profile[j].nbrPoints-1 do begin Aim[CrtNbrLayers+k]:=MyProfile[k];Pparam[CrtNbrLayers+k]:='M';MYN[CrtNbrLayers+k]:=true end; }
                for k:=0 to NrSL do begin Aim[CrtNbrLayers+k]:=Profil[k]*mu0*muB*d[CrtNbrLayers];MYN[CrtNbrLayers+k]:=0 end;
               { traitement particulier pour M : DANGER on met dans le tableau Aim l'aiamnatation en µB/atom }
               { a cause de la densité variable ; ce sera rattrapé par le dernier RefreshParameters }
              if MyProfiles.parameter[j]='theta' then
                 for k:=0 to NrSL do begin theta[CrtNbrLayers+k]:=Profil[k]*Pi/180;thetaYN[CrtNbrLayers+k]:=0 end;
              if MyProfiles.parameter[j]='phi' then
                 for k:=0 to NrSL do begin phi[CrtNbrLayers+k]:=Profil[k]*Pi/180;phiYN[CrtNbrLayers+k]:=0 end;
                   { mise a jour des potentiels est faite a la fin par un appel a refreshparameters }
                   { mise a jour du nombre de couches }
              CrtNbrLayers:=CrtNbrLayers+NrSL;
            end
            end
     else begin { cas ou la couche ne fait pas partie d'un profil }
                {LayerYN[CrtNbrLayers]:=LayerYNaux[i]; }
                MyMultiLayer.Profile[CrtNbrLayers]:=0;
                MyMultiLayer.Description[CrtNbrLayers]:=MLAux.Description[i];
                MyMultiLayer.z[CrtNbrLayers]:=MLAux.z[i];MyMultiLayer.zYN[CrtNbrLayers]:=MLAux.zYN[i];MyMultiLayer.zStep[CrtNbrLayers]:=MLAux.zStep[i];MyMultiLayer.zCorr[CrtNbrLayers]:=MLAux.zCorr[i];
                MyMultiLayer.d[CrtNbrLayers]:=MLAux.d[i];MyMultiLayer.dYN[CrtNbrLayers]:=MLAux.dYN[i];MyMultiLayer.dStep[CrtNbrLayers]:=MLAux.dStep[i];MyMultiLayer.dCorr[CrtNbrLayers]:=MLAux.dCorr[i];
                MyMultiLayer.bn[CrtNbrLayers]:=MLAux.bn[i];MyMultiLayer.bYN[CrtNbrLayers]:=MLAux.bYN[i];MyMultiLayer.bStep[CrtNbrLayers]:=MLAux.bStep[i];MyMultiLayer.bCorr[CrtNbrLayers]:=MLAux.bCorr[i];
                MyMultiLayer.bni[CrtNbrLayers]:=MLAux.bni[i];MyMultiLayer.biYN[CrtNbrLayers]:=MLAux.biYN[i];MyMultiLayer.biStep[CrtNbrLayers]:=MLAux.biStep[i];MyMultiLayer.biCorr[CrtNbrLayers]:=MLAux.biCorr[i];
                MyMultiLayer.f[CrtNbrLayers]:=MLAux.f[i];MyMultiLayer.fYN[CrtNbrLayers]:=MLAux.fYN[i];MyMultiLayer.fStep[CrtNbrLayers]:=MLAux.fStep[i];MyMultiLayer.fCorr[CrtNbrLayers]:=MLAux.fCorr[i];
                MyMultiLayer.fi[CrtNbrLayers]:=MLAux.fi[i];MyMultiLayer.fiYN[CrtNbrLayers]:=MLAux.fiYN[i];MyMultiLayer.fiStep[CrtNbrLayers]:=MLAux.fiStep[i];MyMultiLayer.fiCorr[CrtNbrLayers]:=MLAux.fiCOrr[i];
                { ACHTUNG : on garde Aim en µB/atom pour ne pas interferer avec la densité }
                if MLAux.d[i]<>0 then MyMultiLayer.Aim[CrtNbrLayers]:=MLAux.Aim[i]/(mu0*muB*MLAux.d[i]);
                MyMultiLayer.MYN[CrtNbrLayers]:=MLAux.MYN[i];MyMultiLayer.AimStep[CrtNbrLayers]:=MLAux.AimStep[i];MyMultiLayer.MCorr[CrtNbrLayers]:=MLAux.MCorr[i];
                MyMultiLayer.theta[CrtNbrLayers]:=MLAux.theta[i];MyMultiLayer.thetaYN[CrtNbrLayers]:=MLAux.thetaYN[i];MyMultiLayer.thetaStep[CrtNbrLayers]:=MLAux.thetaStep[i];MyMultiLayer.thetaCOrr[CrtNbrLayers]:=MLAux.thetaCOrr[i];
                MyMultiLayer.phi[CrtNbrLayers]:=MLAux.phi[i];MyMultiLayer.phiYN[CrtNbrLayers]:=MLAux.phiYN[i];MyMultiLayer.phiStep[CrtNbrLayers]:=MLAux.phiStep[i];MyMultiLayer.phiCorr[CrtNbrLayers]:=MLAux.phiCorr[i];
                MyMultiLayer.Sigma[CrtNbrLayers]:=MLAux.Sigma[i];MyMultiLayer.SigYN[CrtNbrLayers]:=MLAux.SigYN[i];MyMultiLayer.SigmaStep[CrtNbrLayers]:=MLAux.SigmaStep[i];MyMultiLayer.SigmaCorr[CrtNbrLayers]:=MLAux.SigmaCorr[i];
                MyMultiLayer.Xsi[CrtNbrLayers]:=MLAux.Xsi[i];{ XsiYN[CrtNbrLayers]:=XsiYNAux[i];}
                MyMultiLayer.Exph[CrtNbrLayers]:=MLAux.Exph[i];{ ExphYN[CrtNbrLayers]:=ExphYNAux[i];}
          end;
      inc(CrtNbrLayers);
      inc(i);
    end;
    With MyMultiLayer do
    begin
       nbrLayers:=CrtNbrLayers;
       z.size(CrtNbrLayers,false);
       bn.size(CrtNbrLayers,false);bni.size(CrtNbrLayers,false);
       f.size(CrtNbrLayers,false);fi.size(CrtNbrLayers,false);
       d.size(CrtNbrLayers,false);
       Aim.size(CrtNbrLayers,false);theta.size(CrtNbrLayers,false);phi.size(CrtNbrLayers,false);
       BeffMag.size(CrtNbrLayers,false);BeffTheta.size(CrtNbrLayers,false);BeffPhi.size(CrtNbrLayers,false);
       V.size(CrtNbrLayers,false);Vi.size(CrtNbrLayers,false);
       Vup.size(CrtNbrLayers,false);Vdo.size(CrtNbrLayers,false);
       sigma.size(CrtNbrLayers,false);xsi.size(CrtNbrLayers,false);exph.size(CrtNbrLayers,false);
    end;
    { mise a jour de la grille MultiLayerGrid }
    UploadMultiLayerGrid(MyMultiLayer,MultiLayerGrid);
end;

procedure TSimulReflecWindow.JvMultilineButton4Click(Sender: TObject);
begin
   if (MyMultiLayerBeforeProfiling.nbrLayers<>0) then MyMultiLayer.clone(MyMultiLayerBeforeProfiling);
   UploadMultiLayerGrid(MyMultiLayer,MultiLayerGrid);
   FlagProfiling.caption:='Non profiled ML'
end;

{ tracé des coefficients R et T intermédiaires }
{ INPUT : theta in min, max , step              }
{ OUTPUT : les deux courbes R et T (en module) dans la liste UnD }
procedure TSimulReflecWindow.CalculateIntermediateRTClick(Sender: TObject);
var i,idx,nrPoints,nbrLayers,indR,indT,indRu,indTu,indRd,indTd:integer;
    AMin,AMax,AStep,ACrt,Qz:double;
    MyML:TMultiLayer;
    kz,AR,AT:Tvec;
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyML:=MyMultiLayer;
   amax:=ThetaDiffMax.value;amin:=ThetaDiffMin.value;aStep:=ThetaDiffStep.value;
   nrPoints:=round((Amax-Amin)/Astep)+1;
   nbrLayers:=MyML.nbrLayers;
   createIt(kz,AR,AT);
   kz.Size(nbrLayers,true);AR.Size(nbrLayers,true);AT.Size(nbrLayers,true);
   idx:=LayerNr.value-1; { idx = 0 correspond au substrat }
   if (MyExperimentalParameters.PolarisationType='non polarised')
   then begin indR:=und.addSpectre('R'+IntToStr(LayerNr.value),nrPoints,1,1);indT:=und.addSpectre('T'+IntToStr(LayerNr.value),nrPoints,1,1); end;
   if (MyExperimentalParameters.PolarisationType='polarised')
   then begin indRu:=und.addSpectre('Ru'+IntToStr(LayerNr.value),nrPoints,1,1);indTu:=und.addSpectre('Tu'+IntToStr(LayerNr.value),nrPoints,1,1);
              indRd:=und.addSpectre('Rd'+IntToStr(LayerNr.value),nrPoints,1,1);indTd:=und.addSpectre('Td'+IntToStr(LayerNr.value),nrPoints,1,1); end;
   for i:=0 to nrPoints-1 do
   begin
      ACrt:=AMin+i*Astep;
      Qz:=4*Pi/MyExperimentalParameters.lambda*sin(aCrt*Pi/180);
      if (MyExperimentalParameters.PolarisationType='non polarised')
      then begin
           CalculReflecNPamplitudes(-Qz,MyML.z,MyML.V,MyML.Vi,MyML.sigma,kz,AR,AT);
           und.spect[indR].data[i,0,0].x:=aCrt;und.spect[indR].data[i,0,0].z:=Cabs(AR.Cvalues[idx]);
           und.spect[indT].data[i,0,0].x:=aCrt;und.spect[indT].data[i,0,0].z:=Cabs(AT.Cvalues[idx]); end;
      if (MyExperimentalParameters.PolarisationType='polarised')
      then begin
           CalculReflecNPamplitudes(-Qz,MyML.z,MyML.Vup,MyML.Vi,MyML.sigma,kz,AR,AT);
           und.spect[indRu].data[i,0,0].x:=aCrt;und.spect[indRu].data[i,0,0].z:=Cabs(AR.Cvalues[idx]);
           und.spect[indTu].data[i,0,0].x:=aCrt;und.spect[indTu].data[i,0,0].z:=Cabs(AT.Cvalues[idx]);
           CalculReflecNPamplitudes(-Qz,MyML.z,MyML.Vdo,MyML.Vi,MyML.sigma,kz,AR,AT);
           und.spect[indRd].data[i,0,0].x:=aCrt;und.spect[indRd].data[i,0,0].z:=Cabs(AR.Cvalues[idx]);
           und.spect[indTd].data[i,0,0].x:=aCrt;und.spect[indTd].data[i,0,0].z:=Cabs(AT.Cvalues[idx]); end;
   end;
end;

procedure TSimulReflecWindow.LambdaDistChoiceClick(Sender: TObject);
begin
     if LambdaDistChoice.itemIndex=1
     then begin lambdaBox.enabled:=false;dlambdaBox.enabled:=false;lambdaSheet.enabled:=false end
     else begin lambdaBox.enabled:=true;dlambdaBox.enabled:=true;lambdaSheet.enabled:=true end;
end;

procedure TSimulReflecWindow.ThetaDistChoiceClick(Sender: TObject);
begin
     if ThetaDistChoice.itemIndex=1
     then begin dThetaBox.enabled:=false;thetaSheet.enabled:=false end
     else begin dThetaBox.enabled:=true;thetaSheet.enabled:=true end;
end;

procedure TSimulReflecWindow.dQzvstheta1Click(Sender: TObject);
var i,ind:integer;
    nbPts:integer;
    sig,theta0,dQz:double; { angle d'incidence }
    MyEP:TExperimentalParameters;
begin
   MyEP:=MyExperimentalParameters;
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   nbPts:=MyDataCalc.Qz.length;
   ind:=und.addspectre('dQz/Qz',nbPts,1,1);
   for i:=0 to MyDataCalc.Qz.length-1 do
   begin
     theta0:=MydataCalc.angles.values[i]; { il faut que les angles existent !!! }
     { dQz:=Qz.values[i]*sqrt(sqr(MyExpParam.dtheta/theta0)+sqr(MyExpParam.dlambda/MyExpParam.lambda)); }
     dQz:=MydataCalc.Qz.values[i]*(abs(MyEP.dtheta/theta0)+abs(MyEP.dlambda/MyEP.lambda));
     sig:=dQz/2;
     und.spect[ind].data[i,0,0].x:=MyDatacalc.Qz.values[i]*1e-9;
     und.spect[ind].data[i,0,0].z:=(sig/MyDatacalc.Qz.values[i]);
   end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

procedure TSimulReflecWindow.QzFast1Click(Sender: TObject);
var i,ind,nbPts:integer;
begin
   MyDataCalc.GenerateQzFast(MyExperimentalParameters);
   { soit a plotter ces points }
   nbPts:=MyDataCalc.QzFast.length;
   ind:=und.addspectre('QzFast',nbPts,1,1);
   for i:=0 to MyDataCalc.QzFast.length-1 do
   begin
     und.spect[ind].data[i,0,0].x:=i;
     und.spect[ind].data[i,0,0].z:=MyDatacalc.QzFast.values[i]*1e-9;
   end;
   { plot de la distribution Qzfast sur le graph Reflectivité }
   for i:=0 to MyDataCalc.QzFast.length-1 do
   begin
      SRGraph1DForm.xyGraph[SerieRexpSFDU][MyDataCalc.QzFast[i]*1e-9]:=1;
   end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

procedure TSimulReflecWindow.dQzInQzIn1Click(Sender: TObject);
var i,j:integer;
    nbPts:integer;
    ind:integer; { tableau des indices des courbes QzSpectrum }
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   nbPts:=MyDataCalc.QzIntensity.length;
   ind:=und.addspectre('dQzIn/QzIn',MyDataCalc.QzSpectrum[0].length,1,1);
   for j:=0 to MyDataCalc.QzSpectrum[0].length-1 do
     begin
        und.spect[ind].data[j,0,0].x:=MyDataCalc.QzSpectrum[trunc(nbPts/2)].values[j]*1e-9;
        und.spect[ind].data[j,0,0].z:=abs(MyDataCalc.QzSpectrum[0].values[j]-MyDataCalc.QzSpectrum[nbPts-1].values[j])/MyDataCalc.QzSpectrum[trunc(nbPts/2)].values[j];
     end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

{=======================================================================================================================================}
{=======================================================================================================================================}
{ CALCULS DIFFRACTION DE SURFACE                                                                                                        }
{=======================================================================================================================================}
{=======================================================================================================================================}

procedure TSimulReflecWindow.CalculGIDClick(Sender: TObject);
var
   nbrlayers:integer;
   kzi,ARi,ATi,kzf,ARf,ATf:Tvec;
   Qzi,Qzf,Sq,a0,Sqbis,SqSub:double;
   Qz,QzSub:Tcplx;
   Ti,Tfstep,Tfstart,Tf,Thetac:double;
   NbrPoints:integer;
   i,j,indGID1,indGID2,indGID3,indGID4,indGID5:integer;
   li,lf,lSB,Sdepth,delta,beta,p,SdepthSub:double;
   aux:Tcplx;
   mindex:integer;
   amin,amax,astep,Outmin,Outmax,Outstep:double; { angles d'incidences et de sortie }
   lambda:double;          { longueur d'onde }
   MyML:TMultilayer;
   bm,deltaup,deltado,deltanp:double;
   s:string;
   QzGID:Tcplx;
begin
  { lSB fonctionne normalement }
  { Sdepth est a peu pres ok avec theta in = 0.34 }
  { Sdepth est très sensible à theta in }
  { mise a jour des paramètres experimentaux }
  UpdateVarExperimentalParameters(MyExperimentalParameters);
  { mise a jour des paramètres de la multicouche a partir de la grille }
  MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
  MyML:=MyMultilayer;

  nbrLayers:=MyML.nbrLayers;
  createIt(kzi,ARi,ATi);createIt(kzf,ARf,ATf);
  kzi.Size(nbrLayers,true);ARi.Size(nbrLayers,true);ATi.Size(nbrLayers,true);
  kzf.Size(nbrLayers,true);ARf.Size(nbrLayers,true);ATf.Size(nbrLayers,true);
  lambda:=MyExperimentalParameters.lambda;
  Amin:=ThetaInGIDmin.value*pi/180;Astep:=ThetaInGIDstep.value*pi/180;Amax:=ThetaInGIDmax.value*pi/180;
  Qzi:=4*pi/lambda*sin(amin); { vecteur de diffusion }
  CalculReflecNPamplitudes(Qzi,MyML.z,MyML.V,MyML.Vi,MyML.sigma,kzi,ARi,ATi);

  { calcul de la dernière couche }
  delta:=sqr(lambda)*MyML.d[nbrLayers-2]*MyML.bn[nbrLayers-2]/(2*pi);
  beta:=sqr(lambda)*MyML.d[nbrLayers-2]*MyML.bni[nbrLayers-2]/(2*pi); { verifier les conventions sur les signes }

  OutMin:=ThetafMin.Value*Pi/180;OutStep:=ThetafStep.Value*Pi/180;OutMax:=ThetafMax.Value*Pi/180;

  li:=sqrt((2*delta-sqr(sin(Amin)))+sqrt(sqr(sqr(sin(Amin))-2*delta)+sqr(2*beta)))/sqrt(2);

  NbrPoints:=round((OutMax-OutMin)/OutStep)+1;
  indGID1:=und.addspectre('ScattDepth',NbrPoints,1,1);
  indGID2:=und.addspectre('SpQ',NbrPoints,1,1);
  indGID3:=und.addspectre('lSB',NbrPoints,1,1);
  indGID4:=und.addspectre('SqBis',NbrPoints,1,1);
  indGID5:=und.addspectre('Qr',NbrPoints,1,1);

  p:=exceptlayers.value;
  a0:=latticeparameterBox.value*1e-9;
  ThetaC:=sqrt(2*delta);ThetaCGIDbox.value:=Thetac*180/pi;

  for i:=0 to NbrPoints-1 do
  begin
      Tf:=OutMin+OutStep*i;
      und.spect[indGID1].data[i,0,0].x:=Tf/Thetac;
      und.spect[indGID2].data[i,0,0].x:=Tf/Thetac;
      und.spect[indGID3].data[i,0,0].x:=Tf/Thetac;
      und.spect[indGID4].data[i,0,0].x:=Tf/Thetac;
      und.spect[indGID5].data[i,0,0].x:=Tf/Thetac;
      Qzf:=4*Pi/lambda*sin(Tf);
      CalculReflecNPamplitudes(Qzf,MyML.z,MyML.V,MyML.Vi,MyML.sigma,kzf,ARf,ATf);
      Qz:=Csub(kzi.Cvalues[nbrLayers-2],neg(kzf.Cvalues[nbrLayers-2])); { le signe est maintenant conforme avec les notations de Dosch }
      {la procédure CalculNPAmplitudes adopte comme convention un signe positif pour z allant du substrat à la surface
      ainsi tous les "kz" calculés sont négatifs. Dans le cas du GID, "kzf" pointe vers les z positifs, on ajoute donc un signe négatif}

      QzSub:=Csub(kzi.Cvalues[0],neg(kzf.Cvalues[0]));
      lf:=sqrt((2*delta-sqr(sin(Tf)))+sqrt(sqr(sqr(sin(Tf))-2*delta)+sqr(2*beta)))/sqrt(2);
      Sdepth:=lambda/(2*pi*(li+lf));
      und.spect[indGID1].data[i,0,0].z:=Sdepth*1E9;

      Sq:=sqr(Sdepth/a0)*exp(-2*a0*p/Sdepth)/(1+sqr((2*Sdepth/a0)*sin(Qz.Re*a0/2))); { attention au signe }
      und.spect[indGID2].data[i,0,0].z:=Sq{*sqr(Cabs(ATi.Cvalues[nbrlayers-2]))*sqr(Cabs(ATf.Cvalues[nbrlayers-2]))};

      lSB:=lambda/(4*pi*lf);
      und.spect[indGID3].data[i,0,0].z:=lSB*1e9;

      Sqbis:=exp(-2*p*a0/Sdepth)/sqr(Cabs(Csub(C_one,exp(Cmul(C_i,Cmul(Qz,Cplx(a0,0)))))));
      und.spect[indGID4].data[i,0,0].z:=Sqbis;
      und.spect[indGID5].data[i,0,0].z:=Qz.Re*1e-9;

  end;
  sendmessage(principalform.handle,wm_redessine,0,0);
  freeit(kzi,ARi,ATi);freeit(kzf,ARf,ATf);

end;

procedure TSimulReflecWindow.CalcGIDPolClick(Sender: TObject);
var
   nbrlayers:integer;
   kzi,ARi,ATi,kzf,ARf,ATf:Tvec;
   Qzi,Qzf,a0:double;
   Ti,Tfstep,Tfstart,Tf,Thetac:double;
   NbrPoints:integer;
   i,indGID1,indGID2,indGID3:integer;
   li,beta,p:double;
   aux:Tcplx;
   mindex:integer;
   amin,amax,astep,Outmin,Outmax,Outstep:double; { angles d'incidences et de sortie }
   lambda,delta:double;          { longueur d'onde }
   MyML:TMultilayer;
   QzGIDNP,QzGIDUP,QzGIDDo:Tcplx;
   SdepthNp,SdepthUP,SdepthDo,SqNP,SqUP,SqDo:double;
begin
  { lSB fonctionne normalement }
  { Sdepth est a peu pres ok avec theta in = 0.34 }
  { Sdepth est très sensible à theta in }
  { mise a jour des paramètres experimentaux }
  UpdateVarExperimentalParameters(MyExperimentalParameters);
  { mise a jour des paramètres de la multicouche a partir de la grille }
  MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
  MyML:=MyMultilayer;

  nbrLayers:=MyML.nbrLayers;
  createIt(kzi,ARi,ATi);createIt(kzf,ARf,ATf);
  kzi.Size(nbrLayers,true);ARi.Size(nbrLayers,true);ATi.Size(nbrLayers,true);
  kzf.Size(nbrLayers,true);ARf.Size(nbrLayers,true);ATf.Size(nbrLayers,true);
  lambda:=MyExperimentalParameters.lambda;
  Amin:=ThetaInGIDmin.value*pi/180;Astep:=ThetaInGIDstep.value*pi/180;Amax:=ThetaInGIDmax.value*pi/180;
  Qzi:=4*pi/lambda*sin(amin); { vecteur de diffusion }
  CalculReflecNPamplitudes(Qzi,MyML.z,MyML.V,MyML.Vi,MyML.sigma,kzi,ARi,ATi);

  OutMin:=ThetafMin.Value*Pi/180;OutStep:=ThetafStep.Value*Pi/180;OutMax:=ThetafMax.Value*Pi/180;

  NbrPoints:=round((OutMax-OutMin)/OutStep)+1;
  indGID1:=und.addspectre('SqNP',NbrPoints,1,1);
  indGID2:=und.addspectre('SqUP',NbrPoints,1,1);
  indGID3:=und.addspectre('SqDO',NbrPoints,1,1);

  p:=exceptlayers.value;
  a0:=latticeparameterBox.value*1e-9;
  delta:=sqr(lambda)*MyML.d[nbrLayers-2]*MyML.bn[nbrLayers-2]/(2*pi);
  ThetaC:=sqrt(2*delta);ThetaCGIDbox.value:=Thetac*180/pi;

  for i:=0 to NbrPoints-1 do
  begin
      Tf:=OutMin+OutStep*i;
      und.spect[indGID1].data[i,0,0].x:=Tf/Thetac;
      und.spect[indGID2].data[i,0,0].x:=Tf/Thetac;
      und.spect[indGID3].data[i,0,0].x:=Tf/Thetac;
      Qzf:=4*Pi/lambda*sin(Tf);
      QzGIDPol('np',Qzi,Qzf,MyML,MyExperimentalParameters,QzGIDnp);
      QzGIDPol('up',Qzi,Qzf,MyML,MyExperimentalParameters,QzGIDup);
      QzGIDPol('do',Qzi,Qzf,MyML,MyExperimentalParameters,QzGIDdo);
      SdepthNP:=1/abs(QzGIDNP.im);
      SdepthUP:=1/abs(QzGIDUP.im);
      SdepthDO:=1/abs(QzGIDDo.im);
      SqNP:=exp(-2*p*a0/SdepthNP)/sqr(Cabs(Csub(C_one,exp(Cmul(C_i,Cmul(QzGIDNP,Cplx(a0,0)))))));
      SqUP:=exp(-2*p*a0/SdepthUP)/sqr(Cabs(Csub(C_one,exp(Cmul(C_i,Cmul(QzGIDUP,Cplx(a0,0)))))));
      SqDO:=exp(-2*p*a0/SdepthDO)/sqr(Cabs(Csub(C_one,exp(Cmul(C_i,Cmul(QzGIDDO,Cplx(a0,0)))))));

      und.spect[indGID1].data[i,0,0].z:=SqNP;
      und.spect[indGID2].data[i,0,0].z:=SqUP;
      und.spect[indGID2].data[i,0,0].z:=SqDO;
  end;
sendmessage(principalform.handle,wm_redessine,0,0);
freeit(kzi,ARi,ATi);freeit(kzf,ARf,ATf);
end;

procedure TSimulReflecWindow.GenerateGIDSpectres;
var bn,bm,bmpar,bmper:double;
    MyML:Tmultilayer;
    lambda:double;
    nbrlayers,indGID1,indGiD2,IndGID3,indGID4,nbrOutPts,nbrInPts,s,i,j,k,l,dQnbri,dQnbrf:integer;
    Outmin,Outstep,OutMax,InMin,InStep,InMax:double;
    thetai,thetaf,dthetai,dthetaf,Qzi,Qzf,qziaux,Qzfaux,dQzi,dQzf,sigi,sigf,dqi,dqf:double;
    aux,Stupup,Stdodo,Stdoup,Stupdo,Stupupaux,Stdodoaux,Stdoupaux,Stupdoaux:double;
    layerIdx:integer;
    latticeParameter:double;
    kziUP,ARiUP,ATiUP,kziDO,ARiDO,ATiDO:Tvec;
    kzfUP,ARfUP,ATfUP,kzfDO,ARfDO,ATfDO:Tvec;
    kziUP_A,ARiUP_A,ATiUP_A,kziDO_A,ARiDO_A,ATiDO_A:array[0..1000] of Tvec;
    kzfUP_A,ARfUP_A,ATfUP_A,kzfDO_A,ARfDO_A,ATfDO_A:array[0..1000] of Tvec;
    kmin,kmax,lmin,lmax:integer;
    QzStepi,QzStepf:double;
    totalIntensity:double;
begin
layerIdx:=layeridxbox.value-1;
latticeParameter:=latticeparameterbox.value*1e-9;
lambda:=MyExperimentalParameters.lambda;
StopFittingFlag:=false;
{ mise a jour des paramètres experimentaux }
UpdateVarExperimentalParameters(MyExperimentalParameters);
{ mise a jour des paramètres de la multicouche a partir de la grille }
MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
MyML:=MyMultilayer;

nbrlayers:=MyML.nbrLayers;
createIt(kziUP,kzfUP,ARiUP,ATiUP);createIt(ARfUP,ATfUP);
kziUP.Size(nbrLayers,true);ARiUP.Size(nbrLayers,true);ATiUP.Size(nbrLayers,true);
kzfUP.Size(nbrLayers,true);ARfUP.Size(nbrLayers,true);ATfUP.Size(nbrLayers,true);
createIt(kziDO,kzfDO,ARiDO,ATiDO);createIt(ARfDO,ATfDO);
kziDO.Size(nbrLayers,true);ARiDO.Size(nbrLayers,true);ATiDO.Size(nbrLayers,true);
kzfDO.Size(nbrLayers,true);ARfDO.Size(nbrLayers,true);ATfDO.Size(nbrLayers,true);
for i:=0 to 1000 do
begin
    createIt(kziUP_A[i],ARiUP_A[i],ATiUP_A[i]);createIt(kziDO_A[i],ARiDO_A[i],ATiDO_A[i]);
    createIt(kzfUP_A[i],ARfUP_A[i],ATfUP_A[i]);createIt(kzfDO_A[i],ARfDO_A[i],ATfDO_A[i]);
end;

OutMin:=ThetafMin.Value*Deg;OutStep:=ThetafStep.Value*Deg;OutMax:=ThetafMax.Value*Deg;
NbrOutPts:=round((OutMax-OutMin)/OutStep)+1;
InMin:=ThetainGIDMin.Value*Deg;InStep:=ThetaInGIDStep.Value*Deg;InMax:=ThetaInGIDMax.Value*Deg;
NbrInPts:=round((InMax-InMin)/InStep)+1;

indGID1:=deuxd.addspectre('StUPUP',NbrInPts,NbrOutPts,1);
deuxd.spect[indGID1].typeX:='deg';
deuxd.spect[indGID1].typeY:='deg';
indGID2:=deuxd.addspectre('StDODO',NbrInPts,NbrOutPts,1);
deuxd.spect[indGID2].typeX:='deg';
deuxd.spect[indGID2].typeY:='deg';
indGID3:=deuxd.addspectre('StDOUP',NbrInPts,NbrOutPts,1);
deuxd.spect[indGID3].typeX:='deg';
deuxd.spect[indGID3].typeY:='deg';
indGID4:=deuxd.addspectre('StUPDO',NbrInPts,NbrOutPts,1);
deuxd.spect[indGID4].typeX:='deg';
deuxd.spect[indGID4].typeY:='deg';

{affichage de l'angle cirtique avec entre parentheses la correction pour le cas magnetique
ThetacGIDBox.text:=floattostrf(sqrt(sqr(lambda/(2*pi))*MyML.V[nbrlayers-2]/hb2over2mn)*Rad,ffGeneral,2,3)
+' ('+floattostrf((sqrt(sqr(lambda/(2*pi))*MyML.Vup[nbrlayers-2]/hb2over2mn)-sqrt(sqr(lambda/(2*pi))*MyML.V[nbrlayers-2]/hb2over2mn))*Rad,ffGeneral,2,3)+')';}

ProgressGID.Max:=NbrInPts;
ProgressGID.Step:=1;
ProgressGID.position:=0;
{ calcul du tableau des vecteurs d'ondes et des amplitudes dans chaque couche }
for i:=0 to NbrInPts-1 do
  begin
  thetai:=InMin+InStep*i;
  Qzi:=4*pi/lambda*sin(thetai);
  CalculReflecNPamplitudes(Qzi,MyML.z,MyML.Vup,MyML.Vi,MyML.sigma,kziUP,ARiUP,ATiUP);
  CalculReflecNPamplitudes(Qzi,MyML.z,MyML.Vdo,MyML.Vi,MyML.sigma,kziDO,ARiDO,ATiDO);
  kziUP_A[i].copy(kziUP);kziDO_A[i].copy(kziDO);
  ARiUP_A[i].copy(ARiUP);ATiUP_A[i].copy(ATiUP);
  ARiDO_A[i].copy(ARiDO);ATiDO_A[i].copy(ATiDO);
  end;
for i:=0 to NbrOutPts-1 do
  begin
  thetaf:=Outmin+OutStep*i;
  Qzf:=4*pi/lambda*sin(thetaf);
  CalculReflecNPamplitudes(Qzf,MyML.z,MyML.Vup,MyML.Vi,MyML.sigma,kzfUP,ARfUP,ATfUP);
  CalculReflecNPamplitudes(Qzf,MyML.z,MyML.Vdo,MyML.Vi,MyML.sigma,kzfDO,ARfDO,ATfDO);
  kzfUP_A[i].copy(kzfUP);kzfDO_A[i].copy(kzfDO);
  ARfUP_A[i].copy(ARfUP);ATfUP_A[i].copy(ATfUP);
  ARfDO_A[i].copy(ARfDO);ATfDO_A[i].copy(ATfDO);
  end;

for i:=0 to (NbrInPts-1) do
  begin
  thetai:=InMin+InStep*i;
  Qzi:=4*pi/lambda*sin(thetai);
  ProgressGID.StepIt;
        for j:=0 to (NbrOutPts-1) do
        begin
        thetaf:=Outmin+OutStep*j;
        Qzf:=4*pi/lambda*sin(thetaf);
        Stupup:=0;Stdodo:=0;Stupdo:=0;Stdoup:=0;
        if ResolutionGID.checked=false then
        begin
        CalculSGuntherM2(layerIdx,latticeparameter,GIDTermsGroup.itemindex,
                        kziUP_A[i],ARiUP_A[i],ATiUP_A[i],kziDO_A[i],ARiDO_A[i],ATiDO_A[i],
                        kzfUP_A[j],ARfUP_A[j],ATfUP_A[j],kzfDO_A[j],ARfDO_A[j],ATfDO_A[j],
                        MyML,MyExperimentalParameters,Stupup,Stdodo,Stupdo,Stdoup);
        end
        else
        begin { calcul avec convolution }
          if (i+1)<=(NbrInPts-1)
          then QzStepi:=abs((kziUP_A[i+1].Cvalues[nbrLayers-1].re*2-kziUP_A[i].Cvalues[nbrLayers-1].re*2))
          else QzStepi:=abs((kziUP_A[i].Cvalues[nbrLayers-1].re*2-kziUP_A[i-1].Cvalues[nbrLayers-1].re*2));
          if (j+1)<=(NbrOutPts-1)
          then QzStepf:=abs((kziUP_A[j+1].Cvalues[nbrLayers-1].re*2-kziUP_A[j].Cvalues[nbrLayers-1].re*2))
          else QzStepf:=abs((kziUP_A[j].Cvalues[nbrLayers-1].re*2-kziUP_A[j-1].Cvalues[nbrLayers-1].re*2));
          dQzi:=Qzi*sqrt(sqr(MyExperimentalParameters.dTheta/thetai)+sqr(MyExperimentalParameters.dlambda/lambda));
          dQzf:=Qzf*sqrt(sqr(MyExperimentalParameters.dTheta/thetaf)+sqr(MyExperimentalParameters.dlambda/lambda));
          sigi:=dQzi/2;sigf:=dQzf/2;

          dQNbri:=round(sigi/QzStepi*MyExperimentalParameters.QzMult);
          dQNbrf:=round(sigf/QzStepf*MyExperimentalParameters.QzMult);
{          dQNbri:=3;dQNbrf:=3; }
          if (i-dQNbri)<0 then kmin:=0 else kmin:=(i-dQNbri);
          if (i+dQNbri)>(NbrInPts-1) then kmax:=NbrInPts-1 else kmax:=(i+dQNbri);
          if (j-dQNbrf)<0 then lmin:=0 else lmin:=(j-dQNbrf);
          if (j+dQNbrf)>(NbrOutPts-1) then lmax:=NbrOutPts-1 else lmax:=(j+dQNbrf);
          TotalIntensity:=0;
          for k:=kmin to kmax do
          begin
             for l:=lmin to lmax do
             begin
                CalculSGuntherM2(layerIdx,latticeparameter,GIDTermsGroup.itemindex,
                        kziUP_A[k],ARiUP_A[k],ATiUP_A[k],kziDO_A[k],ARiDO_A[k],ATiDO_A[k],
                        kzfUP_A[l],ARfUP_A[l],ATfUP_A[l],kzfDO_A[l],ARfDO_A[l],ATfDO_A[l],
                        MyML,MyExperimentalParameters,StupupAux,StdodoAux,StupdoAux,StdoupAux);
                aux:=1/(sigi*sqrt(2*pi))*exp(-(sqr(kziUP_A[k].Cvalues[nbrLayers-1].re*2-kziUP_A[i].Cvalues[nbrLayers-1].re*2)/(2*sigi*sigi)))
                    *1/(sigf*sqrt(2*pi))*exp(-(sqr(kzfUP_A[l].Cvalues[nbrLayers-1].re*2-kzfUP_A[j].Cvalues[nbrLayers-1].re*2)/(2*sigf*sigf)));
                Stupup:=Stupup+StupupAux*aux;
                Stdodo:=Stdodo+StdodoAux*aux;
                Stupdo:=Stupdo+StupdoAux*aux;
                Stdoup:=Stdoup+StdoupAux*aux;
                totalIntensity:=totalIntensity+aux;
             end;
          end;
          Stupup:=Stupup/totalIntensity;
          Stdodo:=Stdodo/totalIntensity;
          Stupdo:=Stupdo/totalIntensity;
          Stdoup:=Stdoup/totalIntensity;
        end;

        deuxd.spect[indGID1].data[i,j,0].x:=thetai*Rad;
        deuxd.spect[indGID1].data[i,j,0].y:=thetaf*Rad;
        deuxd.spect[indGID1].data[i,j,0].z:=Stupup;

        deuxd.spect[indGID2].data[i,j,0].x:=thetai*Rad;
        deuxd.spect[indGID2].data[i,j,0].y:=thetaf*Rad;
        deuxd.spect[indGID2].data[i,j,0].z:=Stdodo;

        deuxd.spect[indGID3].data[i,j,0].x:=thetai*Rad;
        deuxd.spect[indGID3].data[i,j,0].y:=thetaf*Rad;
        deuxd.spect[indGID3].data[i,j,0].z:=Stdoup;

        deuxd.spect[indGID4].data[i,j,0].x:=thetai*Rad;
        deuxd.spect[indGID4].data[i,j,0].y:=thetaf*Rad;
        deuxd.spect[indGID4].data[i,j,0].z:=Stupdo;
        end;
  Application.processMessages; { l'utilisateur a-t-il appuyé sur le boutton ? }
  if StopFittingFlag=true then break; { on sort du calcul }
  end;

  for i:=0 to 1000 do
  begin
    freeIt(kziUP_A[i],ARiUP_A[i],ATiUP_A[i]);freeIt(kziDO_A[i],ARiDO_A[i],ATiDO_A[i]);
    freeIt(kzfUP_A[i],ARfUP_A[i],ATfUP_A[i]);freeIt(kzfDO_A[i],ARfDO_A[i],ATfDO_A[i]);
  end;
  freeit(kziUP,kzfUP,kziDO,kzfDO);
  freeit(ARiUP,ATiUP,ARfUP,ATfUP);
  freeit(ARiDO,ATiDO,ARfDO,ATfDO);
end;

procedure TSimulReflecWindow.CalculGuntherButtonClick(Sender: TObject);
var  nbrlayers,layerindex:integer;
     MyML:TMultilayer;
     bm,bn,bmper,bmpar,pol:double;

begin
{ mise a jour des paramètres experimentaux }
UpdateVarExperimentalParameters(MyExperimentalParameters);
{ mise a jour des paramètres de la multicouche a partir de la grille }
MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
MyDataCalc.updateWithRange(MyExperimentalParameters);

MyML:=MyMultilayer;

GenerateGIDSpectres;

layerindex:=layerIdxBox.value-1;
{Calcul de bm, bmpar (composante parallele) et bmper (composante perpendiculaire) de la couche diffractante}
bm:=(MyML.Vup[layerindex]-MyML.V[layerindex])/(4*pi*hb2over2mn*MyML.d[layerindex]);
bmpar:=bm*FormFactorBox.value*(1-sqr(cos(angleBQ.value*Deg)));
bmper:=bm*FormFactorBox.value*sqr(cos(angleBQ.value*Deg));
bn:=MyML.bn[layerindex];

{Calcul de S(q) a partir des spectres créés dans la procedure CalculSGunther}

deuxd.scalMult(sqr(abs(bn-bmper)),'StUPUP','SUPUP');{nom3=nom2+nom1}
deuxd.scalMult(bmpar*bmper,'StUPDO','SUPDO');
deuxd.addition('SUPUP','SUPDO','SUP');{nom3=nom2+nom1}

deuxd.scalMult(sqr(abs(bn+bmper)),'StDODO','SDODO');
deuxd.scalMult(bmpar*bmper,'StDOUP','SDOUP');
deuxd.addition('SDODO','SDOUP','SDO');{nom3=nom2+nom1}

pol:=polarisationbox.value;
deuxd.scalMult(1+pol,'SUP','SqUP');{nom3=nom2+nom1}
deuxd.scalMult(1-pol,'SDO','SqDO');{nom3=nom2+nom1}

deuxd.addition('SqUP','SqDO','Sq');{nom3=nom2+nom1}
progressGID.Position:=0;
sendmessage(principalform.handle,wm_redessine,0,0);
end;


{cette procédure permet de changer les champs de l'angleBQ, la polarisation, et le FormFactor}
{sans recalculer tous les coeff. Stild}
procedure TSimulReflecWindow.UpdateGIDSetup;
var  nbrlayers,layerindex:integer;
     MyML:TMultilayer;
     bm,bn,bmper,bmpar,pol:double;
begin
if deuxd.IndexOf('Stupup')<>(-1) then
{ mise a jour des paramètres experimentaux }
UpdateVarExperimentalParameters(MyExperimentalParameters);
{ mise a jour des paramètres de la multicouche a partir de la grille }
MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

MyML:=MyMultilayer;
{ nbrlayers:=MyML.nbrlayers;}

layerindex:=layerIdxBox.value-1;
{Calcul de bm, bmpar (composante parallele) et bmper (composante perpendiculaire)}
bm:=(MyML.Vup[layerindex]-MyML.V[layerindex])/(4*pi*hb2over2mn*MyML.d[layerindex]);
bmpar:=bm*FormFactorBox.value*(1-sqr(cos(angleBQ.value*Deg)));
bmper:=bm*FormFactorBox.value*sqr(cos(angleBQ.value*Deg));
bn:=MyML.bn[layerindex];

{Calcul de S(q) a partir des spectres créés dans la procedure CalculSGunther}

deuxd.scalMult(sqr(abs(bn-bmper)),'StUPUP','SUPUP');{nom3=nom2+nom1}
deuxd.scalMult(bmpar*bmper,'StUPDO','SUPDO');
deuxd.addition('SUPUP','SUPDO','SUP');{nom3=nom2+nom1}

deuxd.scalMult(sqr(abs(bn+bmper)),'StDODO','SDODO');
deuxd.scalMult(bmpar*bmper,'StDOUP','SDOUP');
deuxd.addition('SDODO','SDOUP','SDO');{nom3=nom2+nom1}

pol:=polarisationbox.value;
deuxd.scalMult(1+pol,'SUP','SqUP');{nom3=nom2+nom1}
deuxd.scalMult(1-pol,'SDO','SqDO');{nom3=nom2+nom1}

deuxd.addition('SqUP','SqDO','Sq');{nom3=nom2+nom1}
sendmessage(principalform.handle,wm_redessine,0,0);
end;

procedure TSimulReflecWindow.angleBQKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
   UpdateGIDSetup;
end;

procedure TSimulReflecWindow.FormFactorBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  UpdateGIDSetup;
end;

procedure TSimulReflecWindow.StopGIDCalcClick(Sender: TObject);
begin
   StopFittingFlag:=true;
   ProgressGID.position:=0;
end;

procedure TSimulReflecWindow.polarisationBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
   UpdateGIDSetup;
end;

procedure TSimulReflecWindow.layerIdxBoxChange(Sender: TObject);
var MyML:Tmultilayer;
    nbrlayers:integer;
begin
{ mise a jour des paramètres experimentaux }
UpdateVarExperimentalParameters(MyExperimentalParameters);
{ mise a jour des paramètres de la multicouche a partir de la grille }
MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
MyML:=MyMultilayer;
nbrlayers:=MyML.nbrlayers;

layeridxbox.MaxValue:=nbrlayers-1;
end;

procedure TSimulReflecWindow.ThetaCLabelClick(Sender: TObject);
var MyMl:Tmultilayer;
    i,nbrlayers,layerindex:integer;
    lambda:double;
    thetac:string;
begin
{ mise a jour des paramètres experimentaux }
UpdateVarExperimentalParameters(MyExperimentalParameters);
{ mise a jour des paramètres de la multicouche a partir de la grille }
MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
MyML:=MyMultilayer;
lambda:=MyExperimentalParameters.lambda;
nbrlayers:=MyML.nbrlayers;


layerindex:=Thetac_LayerIndex.value-1;
if layerindex<>(-1) then
{affichage de l'angle cirtique avec entre parentheses la correction pour le cas magnetique}
ThetacGIDBox.text:=floattostrf(sqrt(sqr(lambda/(2*pi))*MyML.V[layerindex]/hb2over2mn)*Rad,ffGeneral,2,3)
+' ('+floattostrf((sqrt(sqr(lambda/(2*pi))*MyML.Vup[layerindex]/hb2over2mn)-sqrt(sqr(lambda/(2*pi))*MyML.V[layerindex]/hb2over2mn))*Rad,ffGeneral,2,3)+')';

GIDThetacBox.clear;
for i:=0 to nbrlayers-2 do
        begin
        thetac:=floattostrf(sqrt(sqr(lambda/(2*pi))*MyML.V[i]/hb2over2mn)*Rad,ffFixed,2,2)+' ('+floattostrf((sqrt(sqr(lambda/(2*pi))*MyML.Vup[i]/hb2over2mn)-sqrt(sqr(lambda/(2*pi))*MyML.V[i]/hb2over2mn))*Rad,ffFixed,2,2)+')';
        GIDThetacBox.Items.Add(inttostr(i+1)+'. '+thetac);
        end;

end;

procedure TSimulReflecWindow.ThetaC_LayerIndexChange(Sender: TObject);
var MyML:Tmultilayer;
    nbrlayers:integer;
begin
{ mise a jour des paramètres experimentaux }
UpdateVarExperimentalParameters(MyExperimentalParameters);
{ mise a jour des paramètres de la multicouche a partir de la grille }
MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
MyML:=MyMultilayer;
nbrlayers:=MyML.nbrlayers;

ThetaC_LayerIndex.MaxValue:=nbrlayers-1;
end;

procedure TSimulReflecWindow.SaveMLasXML1Click(Sender: TObject);
var ColNames:Tstrings;
    currentDir:string;
    pBuf:wideString;
begin
  SaveDialogHTML.Filter:='Fichiers XML (*.XML)|*.XML';
  if SaveDialogHTML.Execute then  { Affichage de la boîte de dialogue d'ouverture }
  begin
    GetDir(0,CurrentDir);SaveDialogHTML.InitialDir:=CurrentDir;
    pBuf:=SaveDialogHTML.FileName;
    colNames:=TStringList.Create;
    colNames.Add('Description');
    colNames.Add('density');
    MultiLayerGrid.saveToXML(pBuf,'Zorro','rigolo',colNames);
  end;
  colNames.Free;
end;

procedure TSimulReflecWindow.OpenMLasXML1Click(Sender: TObject);
var pBuf:widestring;
    CurrentDir:string;
begin
end;

{ calcul des R et T pour les différentes interfaces }
{ INPUT : s état de spin; i numéro de l'interface       }
procedure TSimulReflecWindow.CalculateRTvsInterface(s:string;idx:integer;var MyML:TMultiLayer;var MyEP:TExperimentalParameters);
var indR,indT:integer; { indices des spectres pour le module et la phase et les modules de R et T }
    i,nbPts,nbrLayers:integer;
    kz,AR,AT:Tvec;
    Qz:double;
    TinCrt,TinStep,TinMin,TinMAx:double;
begin
{   indR:=-1;indT:=-1; }
   nbrLayers:=MyML.nbrLayers;
   createIt(kz,AR,AT);
   kz.Size(nbrLayers,true);AR.Size(nbrLayers,true);AT.Size(nbrLayers,true);
   nbPts:=round((WFthetaMax.value-WFthetaMin.value)/WFthetaStep.value+1);
   TinStep:=WFthetaStep.value*Deg;
   TinMin:=WFthetaMin.value*Deg;{ TinMax:=WFthetaMax.value*Deg; }
   indR:=und.addspectre('R_'+s,nbPts,1,1);
   indT:=und.addspectre('T_'+s,nbPts,1,1);

   TinCRt:=TinMin;
   for i:=0 to nbPts-1 do
   begin
      Qz:=4*Pi/MyEP.lambda*sin(TinCrt);
      if s='NP' then CalculReflecNPamplitudes(-Qz,MyML.z,MyML.V,MyML.Vi,MyML.sigma,kz,AR,AT);
      if s='UP' then CalculReflecNPamplitudes(-Qz,MyML.z,MyML.Vup,MyML.Vi,MyML.sigma,kz,AR,AT);
      if s='DO' then CalculReflecNPamplitudes(-Qz,MyML.z,MyML.Vdo,MyML.Vi,MyML.sigma,kz,AR,AT);

      und.spect[indR].data[i,0,0].X:=TinCrt/DEG;
      und.spect[indT].data[i,0,0].X:=TinCrt/DEG;
      und.spect[indR].data[i,0,0].Z:=Cabs(AR.Cvalues[idx]);
      und.spect[indT].data[i,0,0].Z:=Cabs(AT.Cvalues[idx]);
      TinCrt:=TinCrt+TinSTep;
   end;
   freeIt(kz,AR,AT);
end;


procedure TSimulReflecWindow.RTvsdepth1Click(Sender: TObject);
var idx:integer;
begin
   idx:=InterfaceIdxBox.value;
   WFcalcStatus.caption:='Calculation running';WFcalcStatus.update;
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   if (MyExperimentalParameters.PolarisationType='non polarised')
   then CalculateRTvsInterface('NP',idx,MyMultiLayer,MyExperimentalParameters);
   if (MyExperimentalParameters.PolarisationType='polarised')
   then begin
          CalculateRTvsInterface('UP',idx,MyMultiLayer,MyExperimentalParameters);
          CalculateRTvsInterface('DO',idx,MyMultiLayer,MyExperimentalParameters);
        end;
   WFcalcStatus.caption:='Idle';WFcalcStatus.update;
   { rafraichissement du graph1D}
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

procedure TSimulReflecWindow.STOPWaveFunctionButtonClick(Sender: TObject);
begin
StopFittingFlag:=true;
end;

procedure TSimulReflecWindow.TypePolarisationDragDrop(Sender,
  Source: TObject; X, Y: Integer);
begin
     if TypePolarisation.text='non polarised'
     then with MultiLayerGrid do
                begin colWidths[colM]:=0;colWidths[colMYN]:=0;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=0;colWidths[colPhiYN]:=0;
                end;
     if TypePolarisation.text='polarised'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=0;colWidths[colPhiYN]:=0;
                end;
     if TypePolarisation.text='with spin-flip'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=colUnit*5;colWidths[colPhiYN]:=colUnit*4;
                end;
     if TypePolarisation.text='with SF high field'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=colUnit*5;colWidths[colThetaYN]:=colUnit*4;
                      colWidths[colPhi]:=colUnit*5;colWidths[colPhiYN]:=colUnit*4;
                end;
end;

procedure TSimulReflecWindow.TypePolarisationExit(Sender: TObject);
begin
     if TypePolarisation.text='non polarised'
     then with MultiLayerGrid do
                begin colWidths[colM]:=0;colWidths[colMYN]:=0;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=0;colWidths[colPhiYN]:=0;
                end;
     if TypePolarisation.text='polarised'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=0;colWidths[colPhiYN]:=0;
                end;
     if TypePolarisation.text='with spin-flip'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=0;colWidths[colThetaYN]:=0;
                      colWidths[colPhi]:=colUnit*5;colWidths[colPhiYN]:=colUnit*4;
                end;
     if TypePolarisation.text='with SF high field'
     then with MultiLayerGrid do
                begin colWidths[colM]:=colUnit*5;colWidths[colMYN]:=colUnit*4;
                      colWidths[colTheta]:=colUnit*5;colWidths[colThetaYN]:=colUnit*4;
                      colWidths[colPhi]:=colUnit*5;colWidths[colPhiYN]:=colUnit*4;
                end;
end;

procedure TSimulReflecWindow.CopyML1intoML21Click(Sender: TObject);
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   { copie de la ML1 dans la ML2 }
   MyMultiLayer2.Clone(MyMultiLayer);
   { mise a jour du panel ML2 à partir des nouvelles data }
   UpLoadMultiLayerGrid(MyMultiLayer2,MultiLayerGrid2);
   SetHeaders(MyExperimentalParameters,MultiLayerGrid2);
end;

procedure TSimulReflecWindow.FitCrawlingPolydomaines1Click(Sender: TObject);
var t0:TDateTime;
    fraction1,fraction2:double;
begin
{   SRGraph1DForm.storeCurves; }
   { on copie les dataExp et on les crops }
   MyDataExpFit.clone(MyDataExp);
   MydataExpFit.crop(FitAbsMin.value,FitAbsMax.value);
   { mise a jour des paramètres experimentaux a partir des informations de la fenetre graphique}
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyMultiLayer2.UpdateFromMultiLayerGrid(MultiLayerGrid2,MyExperimentalParameters);
   { mise a jour des resolutions expérimentales }
   MyDataExpFit.updateWithAbscisses(MyExperimentalParameters);
   { on crée le spectre des data calculées }
   MyDataCalc.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc.updateWithAbscisses(MyExperimentalParameters); { mise a jour des paramètres de résolution }
   { on crée le spectre des data calculées }
   MyDataCalc2.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc2.updateWithAbscisses(MyExperimentalParameters); { mise a jour des paramètres de résolution }
   { on affiche le panneau de fit }
   TabSheetFitting.Tabvisible:=true;PageControl.update;
   t0:=time;

{   MyDataCalc2.updateWithRange(MyExperimentalParameters); }
   fraction1:=fraction1Box.value/(fraction1Box.value+fraction2Box.value);
   fraction2:=fraction2Box.value/(fraction1Box.value+fraction2Box.value);

   if TypePolarisation.text='non polarised'
   then begin
        MinimisationCrawling_PD(RandomnessBox.value,MyExperimentalParameters,MyMultiLayer,MyMultiLayer2,MyProfiles,MyDataExpFit,MyDataCalc,MyDataCalc2);
        { affichage des résultats }
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
        { mise a jour des courbes }
        With MyDataCalc do begin R.Add(MyDataCalc2.R);T.Add(MyDataCalc2.T) end;
        SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.R,SerieRcalcUP);
        Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.R,'R');
        Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.T,'T');
        end;

   if TypePolarisation.text='with spin-flip'
   then begin
        MinimisationCrawling_SF_PD(RandomnessBox.value,MyExperimentalParameters,MyMultiLayer,MyMultiLayer2,MyProfiles,MyDataExpFit,MyDataCalc,MyDataCalc2);
        { affichage des résultats }
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
        { mise a jour des courbes }
        With MyDataCalc do
        begin Ruu.Add(MyDataCalc2.Ruu);Rdd.Add(MyDataCalc2.Rdd);Rud.Add(MyDataCalc2.Rud);Rdu.Add(MyDataCalc2.Rdu);
              Tuu.Add(MyDataCalc2.Tuu);Tdd.Add(MyDataCalc2.Tdd);Tud.Add(MyDataCalc2.Tud);Tdu.Add(MyDataCalc2.Tdu);  end;
        end;

{   SRGraph1Dform.PlotDifference(MyDataExp,MyDataCalc); }
   FittingStatus.caption:='Idle';FittingStatus.update;
   IterCrt.caption:='...';IterCrt.update;
{   ecartBox.value:=difference(MyDataExp,MyDataCalc,MyExperimentalParameters); }
{   if MyMultiLayer.profiled then begin ecartBoxSmooth.value:=MyMultiLayer.SmoothProfile(MyProfiles);ecartBox.value:=ecartBox.value+ecartBoxSmooth.value end; }
   ElapsedTimeBox.Value:=(time-t0)*86400;
{   MyDataCalc.SaveToClipboard; }
   PlayWave('The_Fit_Is_Finished');
end;


procedure TSimulReflecWindow.PolydomainsMenuClick(Sender: TObject);
begin
    If PolyDomainsMenu.checked=true
    then begin
         PolyDomainsEnabledCheckBox.checked:=true;
         PageControl1.ActivePage:=ML2;
         ML2.TabVisible:=true;
         end
    else begin
         PolyDomainsEnabledCheckBox.checked:=false;
         PageControl1.ActivePage:=ML1;
         ML2.TabVisible:=false;
         end;
end;


procedure TSimulReflecWindow.PolyDomainsEnabledCheckBoxClick(
  Sender: TObject);
begin
    If PolyDomainsEnabledCheckBox.checked=true
    then begin
         PolyDomainsEnabledCheckBox.font.Color:=clRed;
         PolyDomainsMenu.checked:=true;
         PageControl1.ActivePage:=ML2;
         ML2.TabVisible:=true;
         end
    else begin
         PolyDomainsEnabledCheckBox.font.Color:=clBlack;
         PolyDomainsMenu.checked:=false;
         PageControl1.ActivePage:=ML1;
         ML2.TabVisible:=false;
         end;

end;

procedure TSimulReflecWindow.ProfilesGridExit(Sender: TObject);
begin
    MyProfiles.update(ProfilesGrid);    
end;

procedure TSimulReflecWindow.dQzvsQz1Click(Sender: TObject);
var i,ind:integer;
    nbPts:integer;
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   nbPts:=MyDataCalc.Qz.length;
   ind:=und.addspectre('dQzFast',nbPts,1,1);
   for i:=1 to MyDataCalc.QzFast.length-1 do
   begin
     und.spect[ind].data[i,0,0].x:=MyDatacalc.QzFast.values[i]*1e-9;
     und.spect[ind].data[i,0,0].z:=(MyDatacalc.QzFast.values[i]-MyDatacalc.QzFast.values[i-1])*1e-9;
   end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

procedure TSimulReflecWindow.dQzvsQzFast1Click(Sender: TObject);
var i,ind:integer;
    nbPts:integer;
    sig,theta0,dQz:double; { angle d'incidence }
    MyEP:TExperimentalParameters;
begin
   MyEP:=MyExperimentalParameters;
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   nbPts:=MyDataCalc.Qz.length;
   ind:=und.addspectre('dQz',nbPts,1,1);
   for i:=0 to MyDataCalc.QzFast.length-1 do
   begin
     theta0:=MydataCalc.angles.values[i]; { il faut que les angles existent !!! }
     { dQz:=Qz.values[i]*sqrt(sqr(MyExpParam.dtheta/theta0)+sqr(MyExpParam.dlambda/MyExpParam.lambda)); }
     dQz:=MydataCalc.QzFast.values[i]*(abs(MyEP.dtheta/theta0)+abs(MyEP.dlambda/MyEP.lambda));
     { sig:=dQz/2; }
     und.spect[ind].data[i,0,0].x:=MyDatacalc.QzFast.values[i]*1e-9;
     und.spect[ind].data[i,0,0].z:=dQz*1e-9;
   end;
   sendmessage(principalform.handle,wm_redessine,0,0);
end;

{ calcul des angles d'incidences dans chaque couche }
{ INPUT : implicite : on utilise les variables TMyMultiLayer et les potentiels V }
{         l'angle d'incidence dans le vide                                      }
{ OUTPUT : dans le memo, la liste des angles de propagation dans la couche s'affichent }
{ on part de l'equation de Schrodinger                                          }
{ Laplacien Psi + 2m/hbar² (E-V) Psi = 0                                        }
{ d'où k² = 2m/hbar (E-V)                                                       }
{ on suppose que k// est conservé                                               }
{ on obtient ki = k0 (1-V/E)                                                    }
procedure TSimulReflecWindow.CalculAlphaButtonClick(Sender: TObject);
var n:integer;
    k0,kpara,E0:double; { vecteur d'onde dans le vide et sa composante planaire}
    k,kz2,angle,Tc:double;
    R,T:double;
    kz0,kz1:TCplx;
begin
   WFMemo.Clear;
   WFMemo.lines.Add('Propagation angles inside the layers for Theta in = '+FloatToStr(WFThetaIN.value));
   k0:=2*pi/MyExperimentalParameters.lambda;
   E0:=hb2*k0*k0/2/mn;
   kpara:=k0*cos(WFThetaIN.value*pi/180);
   { scanning des différentes couches }
   for n:=0 to MyMultiLayer.nbrLayers-1 do { boucle du substrat vers le vide }
   begin
       k:=k0*sqrt((1-MyMultiLayer.V[n]/E0));
       kz2:=k*k-kpara*kpara; { composante en z dans la couche }
       Tc:=180/pi*arccos(sqrt(1-MyMultiLayer.V[n]/E0));
       { coefficients de Fresnel aux interfaces }
       { r = (k0-ks) / (k0+ks) }
       { t = 2 k0 / (k0+ks) }
       if n<>0 { on ne fait pas le calcul pour le vide }
       then begin
            kz0:=Csqrt(cplx(k0*k0*(1-MyMultiLayer.V[n-1]/E0)-kpara*kpara,0)); { couche du dessous }
            kz1:=Csqrt(cplx(k0*k0*(1-MyMultiLayer.V[n]/E0)-kpara*kpara,0));
            R:=Cabs(Csqr(Cdiv(Csub(kz1,kz0),Cadd(kz1,kz0))));
            T:=Cabs(Csqr(Cdiv(Cmul(Cplx(2,0),kz1),Cadd(kz0,kz1))));
            end
       else begin R:=0;T:=1 end;
       if kz2<0
       then WFMemo.lines.add('Layer '+intToStr(n+1)+' : Tc = '+FloatToStrF(Tc,ffFixed,5,3)+' : evanescent wave.')
{                               +' R='+FloatToStrF(R,ffGeneral,5,1)+' T='+FloatToStrF(T,ffGeneral,5,1))            }
       else begin
            angle:=arctan(sqrt(kz2)/kpara)*180/pi;
            WFMemo.lines.add('Layer '+intToStr(n+1)+' : Tc = '+FloatToStrF(Tc,ffFixed,5,3)+' : Angle = '+FloatToStrF(angle,ffFixed,5,3));
{                            +' R='+FloatToStrF(R,ffGeneral,5,5)+' T='+FloatToStrF(T,ffGeneral,5,5)) }
            end;
   end;
end;

{ lecture d'un jeu de data pour la liste des MDS Multiple Data Sets }
{ on fait l'hypothèse que les MDS utilisent les mêmes paramètres expériementaux (pour le moment) }
{ cad cela correspond à la variation d'un paramètre extérieur indépendant du spectromètre }
procedure TSimulReflecWindow.GetDataButtonClick(Sender: TObject);
var i:integer;
    s:string;
begin
  if OpenDialogDataFile.Execute then
  begin
     { mise a jour des paramètres experimentaux }
     UpdateVarExperimentalParameters(MyExperimentalParameters);  { on garde la variable globale MyEP dans ce cas précis puisque toutes les data utilisent le même }
     { mise a jour des paramètres de la multicouche a partir de la grille }
     MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

     s:=OpenDialogDataFile.FileName;
     i:=length(s);while s[i]<>'\' do dec(i);
     MDSpathBox.text:=copy(s,0,i);
     MDSListBox.Items.Strings[MDSSetBox.value-1]:=copy(s,i+1,length(s));
     Setlength(MyMDS,MDSListBox.items.Count);MyMDS[MDSSetBox.value-1]:=TDataReflectivity.create;
     Setlength(MyMDS_EP,MDSListBox.items.Count);MyMDS_EP[MDSSetBox.value-1]:=TExperimentalParameters.create;
     Setlength(MyMDS_ML,MDSListBox.items.Count);MyMDS_ML[MDSSetBox.value-1]:=TMultiLayer.create;MyMDS_ML[MDSSetBox.value-1].Clone(MyMultiLayer);
     UpdateVarExperimentalParameters(MyMDS_EP[MDSSetBox.value-1]); { faut-il faire cet upgrade? } { en principe ca ne peut pas faire de aml puisque les data doivent être compatible }
     { une vérification de la compatibilité des data serait peut-être bienvenue ?}
     MyMDS[MDSSetBox.value-1].ReadFromFile(MyMDS_EP[MDSSetBox.value-1],OpenDialogDataFile.FileName);
     SRGraph1Dform.PlotDataReflectivityMDS(MyMDS[MDSSetBox.value-1],MDSSetBox.value);
     UpdateSimulReflecWindowParameters(MyMDS_EP[MDSSetBox.value-1]);
     MDSIndexBox.MaxValue:=MDSSetBox.value;
     MDSSetBox.value:=MDSSetBox.value+1; { incrément automatique pour le prochain ajout }
     { on fait l'update des lignes et colonnes de la grille  MDSParamsGrid }
     UpdateMDSfreeParams(MyMDS_ML,MyExperimentalParameters);
  end;
end;

{ affichage des différents MDS dans la Grille principales }
procedure TSimulReflecWindow.MDSIndexBoxChange(Sender: TObject);
var i,indexLayer,MDSidx:integer;
begin
    MDSidx:=MDSIndexBox.value-1;
          i:=0;
          indexLayer:=1;
          while i<=(MyMDS_ML[MDSidx].NbrLayers-1) do
          begin
            with MultiLayerGrid do
            begin
              if Uppercase(Cells[ColYN,indexLayer])='Y'
              then with MyMDS_ML[MDSidx] do
                   begin
                   if zYN[i]<>-1 then begin Floats[ColEpaisseur,indexLayer]:=z[i]*1E9 end;if zCorr[i]='L' then Colors[ColEpaisseur,indexLayer]:=clInfoBk;
                   if dYN[i]<>-1 then begin Floats[ColDensity,indexLayer]:=d[i]*1e-28 end;if dCorr[i]='L' then Colors[ColDensity,indexLayer]:=clInfoBk;
                   if MyExperimentalParameters.Particles='xrays'
                   then begin
                              if fYN[i]<>-1 then begin Floats[ColF,indexLayer]:=f[i] end;if fCorr[i]='L' then Colors[ColF,indexLayer]:=clInfoBk;
                              if fiYN[i]<>-1 then begin Floats[ColFi,indexLayer]:=fi[i] end;if fiCorr[i]='L' then Colors[ColFi,indexLayer]:=clInfoBk; end;
                   if MyExperimentalParameters.Particles='neutrons'
                   then begin if bYN[i]<>-1 then begin Floats[ColB,indexLayer]:=bn[i]*1e15 end;if bCorr[i]='L' then Colors[ColB,indexLayer]:=clInfoBk;
                              if biYN[i]<>-1 then begin Floats[ColBi,indexLayer]:=bni[i]*1e15 end;if biCorr[i]='L' then Colors[ColBi,indexLayer]:=clInfoBk;
                              if MyExperimentalParameters.PolarisationType='polarised'
                              then begin if MYN[i]<>-1 then begin Floats[ColM,indexLayer]:=Aim[i]/(mu0*muB*d[i]) end;
                                         if MCorr[i]='L' then Colors[ColM,indexLayer]:=clInfoBk;
                                         end;
                              if (MyExperimentalParameters.PolarisationType='with spin-flip') or (MyExperimentalParameters.PolarisationType='with SF high field')
                              then begin if MYN[i]<>-1 then begin Floats[ColM,indexLayer]:=Aim[i]/(mu0*muB*d[i]) end;if MCorr[i]='L' then Colors[ColM,indexLayer]:=clInfoBk;
                                         if ThetaYN[i]<>-1 then begin Floats[ColTheta,indexLayer]:=Theta[i]*180/pi end;if ThetaCorr[i]='L' then Colors[ColTheta,indexLayer]:=clInfoBk;
                                         if PhiYN[i]<>-1 then begin Floats[ColPhi,indexLayer]:=Phi[i]*180/pi end;if PhiCorr[i]='L' then Colors[ColPhi,indexLayer]:=clInfoBk;
                                         end;
                             end;
                   if sigYN[i]<>-1 then begin Floats[ColSigma,indexLayer]:=sigma[i]*1e9 end;if sigmaCorr[i]='L' then Colors[ColSigma,indexLayer]:=clInfoBk;
                   inc(i);
                   end;
             inc(indexLayer);
            end;
          end;
end;

{ affichage des headers des parametres libres dans la MDS Grid  }
procedure TSimulReflecWindow.UPdateMDSGridColHeaders(var MyMDS_ML:array of TMultilayer;var MyEp:TexperimentalParameters);
var i,j,colIdx:integer;
begin
   { on balaie les MDS_ML }
   for i:=0 to high(MyMDS_ML) do
   begin
      colIdx:=1;
      MDSparamsGrid.ints[0,i+1]:=i+1; { index du MDS }
      with MyMDS_ML[i] do
      begin
          for j:=0 to nbrLayers-1 do
          begin
             if zYN[j]<>-1 then if zCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='z'+intToStr(j+1);inc(colidx) end;
             if dYN[j]<>-1 then if dCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='rho'+intToStr(j+1);inc(colidx)  end;
             if MyEP.particles='neutrons'
             then begin
                  if bYN[j]<>-1 then if bCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='b'+intToStr(j+1);inc(colidx) end;
                  if biYN[j]<>-1 then if biCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='bi'+intToStr(j+1);inc(colidx) end;
                  if MyEP.PolarisationType='polarised' then if MYN[j]<>-1 then if MCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='M'+intToStr(j+1);inc(colidx) end;
                  if (MyEP.polarisationType='with spin-flip') or (MyEP.polarisationType='with SF high field')
                  then begin
                       if MYN[j]<>-1 then if MCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='M'+intToStr(j+1);inc(colidx) end;
                       if ThetaYN[j]<>-1 then if ThetaCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='theta'+intToStr(j+1);inc(colidx) end;
                       if PhiYN[j]<>-1 then if PhiCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='phi'+intToStr(j+1);inc(colidx) end;
                       end;
                  end
             else begin
                  if fYN[j]<>-1 then if fCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='f'+intToStr(j+1);inc(colidx) end;
                  if fiYN[j]<>-1 then if fiCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='fi'+intToStr(j+1);inc(colidx) end;
                  end;
             if sigYN[j]<>-1 then if sigmaCorr[j]='L' then begin MDSparamsGrid.cells[colidx,0]:='sig'+intToStr(j+1);inc(colidx) end;
          end;
      end;
   end
end;

{ affichage des parametres libres dans une AdvStrGrid }
procedure TSimulReflecWindow.UPdateMDSfreeParams(var MyMDS_ML:array of TMultilayer;var MyEp:TexperimentalParameters);
var i,j,colIdx:integer;
begin
   { on balaie les MDS_ML }
   for i:=0 to high(MyMDS_ML) do
   begin
      colIdx:=1;
      MDSparamsGrid.ints[0,i+1]:=i+1; { index du MDS }
      with MyMDS_ML[i] do
      begin
          for j:=0 to nbrLayers-1 do
          begin
             if zYN[j]<>-1 then if zCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='z'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(z[j]*1e9);inc(colidx) end;
             if dYN[j]<>-1 then if dCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='rho'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(d[j]*1e-28);inc(colidx)  end;
             if MyEP.particles='neutrons'
             then begin
                  if bYN[j]<>-1 then if bCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='b'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(bn[j]*1e15);inc(colidx) end;
                  if biYN[j]<>-1 then if biCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='bi'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(bni[j]*1e15);inc(colidx) end;
                  if MyEP.PolarisationType='polarised' then if MYN[j]<>-1 then if MCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='M'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(Aim[j]/(mu0*muB*d[j]));inc(colidx) end;
                  if (MyEP.polarisationType='with spin-flip') or (MyEP.polarisationType='with SF high field')
                  then begin
                       if MYN[j]<>-1 then if MCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='M'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(Aim[j]/(mu0*muB*d[j]));inc(colidx) end;
                       if ThetaYN[j]<>-1 then if ThetaCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='theta'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(Theta[j]*180/pi);inc(colidx) end;
                       if PhiYN[j]<>-1 then if PhiCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='phi'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(Phi[j]*180/pi);inc(colidx) end;
                       end;
                  end
             else begin
                  if fYN[j]<>-1 then if fCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='f'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(f[j]);inc(colidx) end;
                  if fiYN[j]<>-1 then if fiCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='fi'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(fi[j]);inc(colidx) end;
                  end;
             if sigYN[j]<>-1 then if sigmaCorr[j]='L' then begin MDSparamsGrid.ColCount:=colIdx+1;MDSparamsGrid.cells[colidx,0]:='sig'+intToStr(j+1);MDSparamsGrid.floats[colidx,i+1]:=(sigma[j]*1e9);inc(colidx) end;
          end;
      end;
   end;
   if colIdx=1 then MessageDlg('You have not set any free parameter (''L'' index)', mtInformation, [mbOk], 0)
end;

{ mise à jour des paramètres affichés dans la MDSGrid pendant un fit }
procedure  TSimulReflecWindow.updateDisplayWhileFitting(var MyGrid:TAdvStringGrid;var MyMultiLayer:TMultiLayer;var MyExperimentalParameters:TExperimentalParameters;var chi:double);
var i,indexLayer:integer;
begin
   EcartBox.value:=chi;EcartBox.update;
   NormBox.value:=MyExperimentalParameters.NormalisationFactor;NormBox.update;
   { il faut tenir compte des couches desactivées (avec Y/N) }
   i:=0;indexLayer:=1;
   while i<=(MyMultilayer.NbrLayers-1) do
   begin
      with MyGrid do
      begin
         if Uppercase(Cells[ColYN,indexLayer])='Y'
         then with MyMultiLayer do
              begin
                 if zYN[i]<>-1 then begin Floats[ColEpaisseur,indexLayer]:=z[i]*1E9 end;
                 if dYN[i]<>-1 then begin Floats[ColDensity,indexLayer]:=d[i]*1e-28 end;
                 if MyExperimentalParameters.Particles='xrays' then begin
                                    if fYN[i]<>-1 then begin Floats[ColF,indexLayer]:=f[i] end;
                                    if fiYN[i]<>-1 then begin Floats[ColFi,indexLayer]:=fi[i] end; end;
                 if MyExperimentalParameters.Particles='neutrons'
                 then begin
                      if bYN[i]<>-1 then begin Floats[ColB,indexLayer]:=bn[i]*1e15 end;
                      if biYN[i]<>-1 then begin Floats[ColBi,indexLayer]:=bni[i]*1e15 end;
                      if MyExperimentalParameters.polarisationType='polarised'
                      then if MYN[i]<>-1 then begin Floats[ColM,indexLayer]:=Aim[i]/(mu0*muB*d[i]) end;
                      if (MyExperimentalParameters.polarisationType='with spin-flip') or (MyExperimentalParameters.polarisationType='with SF high field')
                      then begin
                           if MYN[i]<>-1 then begin Floats[ColM,indexLayer]:=Aim[i]/(mu0*muB*d[i]) end;
                           if PhiYN[i]<>-1 then begin Floats[ColPhi,indexLayer]:=Phi[i]*180/pi end;
                           if ThetaYN[i]<>-1 then begin Floats[ColTheta,indexLayer]:=Theta[i]*180/pi end;
                           end;
                      end;
                 if sigYN[i]<>-1 then begin Floats[ColSigma,indexLayer]:=sigma[i]*1e9 end;
                 inc(i);
               end;
         inc(indexLayer);
      end;
   end;
end;

{ si on clique sur la box MDS, les paramètres de la grid se mettent a jour }
procedure TSimulReflecWindow.GroupBox28Click(Sender: TObject);
begin
     UpdateMDSfreeParams(MyMDS_ML,MyExperimentalParameters);
end;

{ procedure de calcul du rapport (R++(PHI)-R--(PHI))/(R++(0°)-R--(0°))  }
{ INPUT: le tableau du modèle                                           }
{ OUTPUT: la courbe COS PHI                                             }
{ ATTENTION: calcul complètement incohérent!!!      }
{            Rtotale = Sum (R(lambda))              }
procedure TSimulReflecWindow.CosPHI1Click(Sender: TObject);
var  i:integer;
     fraction1,fraction2,a:double;
     R,T,Rup,Rdo,Tup,Tdo,Ruu,Rdd,Rud,Rdu,Tuu,Tdd,Tud,Tdu:Tvec;
     BeffX,BeffY,BeffZ:double;
begin
   createIt(R,T);createIt(Rup,Rdo,Tup,Tdo);createIt(Ruu,Rdd,Rud,Rdu);createIt(Tuu,Tdd,Tud,Tdu);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataCalc.updateWithRange(MyExperimentalParameters);
   MyDataCalc2.updateWithRange(MyExperimentalParameters);
   MyDataCalc3.updateWithRange(MyExperimentalParameters);

   If polydomainsMenu.checked=true
   then begin
        MyMultiLayer2.UpdateFromMultiLayerGrid(MultiLayerGrid2,MyExperimentalParameters);
        MyDataCalc2.updateWithRange(MyExperimentalParameters);
        fraction1:=fraction1Box.value/(fraction1Box.value+fraction2Box.value);
        fraction2:=fraction2Box.value/(fraction1Box.value+fraction2Box.value);
        end;

   if (typePolarisation.text='non polarised') or (typePolarisation.text='polarised')
   then begin MessageDlg('You need to use the options ''with spin-flip'' or ''with SF high field', mtInformation, [mbOk], 0);exit; end;

   if typePolarisation.text='with spin-flip'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             { calcul de la reflectivity avec PHI = 0° }
             MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
             for i:=0 to MyMultiLayer2.nbrLayers-1 do MyMultiLayer2.phi[i]:=0;             { on remplace les angles phi par la valeur 0 }
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
             MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
             { fin du calcul avec PHI = 0° }
             { calcul de la reflectivity avec PHI = 90° }
             MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
             for i:=0 to MyMultiLayer2.nbrLayers-2 do MyMultiLayer2.phi[i]:=pi/2;       { on remplace les angles phi par la valeur pi/2 suaf le vide !! }
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc3); { on fait le calcul de reflectivité }
             MyDataCalc3.Normalise(MyExperimentalParameters.NormalisationFactor);
             { fin du calcul avec PHI = 90° }

             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSF);
             { on trace COS PHI dans le plot du bas  }
             SetLegendXYGraphPhi('COS PHI and SIN² PHI','Cos Phi calc.','Sin²PHI calc.','-','-');
             for i:=0 to MyDataCalc.Abscisses.length-1 do
             begin
                SRGraph1DForm.xyGraphPhi[SerieCOSPHI][MyDataCalc.Abscisses[i]]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]);
                SRGraph1DForm.xyGraphPhi[SerieSIN2PHI][MyDataCalc.Abscisses[i]]:=MyDataCalc.Rud.values[i]/MyDataCalc3.Rud.values[i];
             end;
             XYGraphPhi_ReleaseUpdate(SerieCOSPHI);XYGraphPhi_ReleaseUpdate(SerieSIN2PHI);
             end;

   if typePolarisation.text='with SF high field'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSFUD);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdu,SerieRcalcSFDU);

             { calcul de la reflectivity avec PHI = 0° }
             MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
             for i:=0 to MyMultiLayer2.nbrLayers-1 do
             begin
                with MyMultiLayer2 do
                begin  { calcul du champ effectif dans chaque couche } { avec PHI = 0; on suppose que le champ est suivant PHI=0 }
                       BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi)+Aim[i];
                       BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi); { zero en principe }
                       BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta); { zero en principe }
                       BeffMag[i]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
                       {definition des angles théta et phi du champ efficace}
                       if BeffMag[i]<>0 then BeffTheta[i]:=ArcCos(BeffZ/BeffMag[i]) else BeffTheta[i]:=0; {en radians}
                       if (BeffX<>0) and (BeffY<>0) then BeffPhi[i]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[i]:=0;{en radians}
                end;
             end;
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
             MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
             { fin du calcul avec PHI = 0° }
             { calcul de la reflectivity avec PHI = 90° }
             MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
             for i:=0 to MyMultiLayer2.nbrLayers-2 do       { on remplace les angles phi par la valeur pi/2 suaf le vide !! }
             begin
                with MyMultiLayer2 do
                begin  { calcul du champ effectif dans chaque couche } { avec PHI = 90°; on suppose que le champ est suivant PHI=0 }
                       BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi);
                       BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi)+Aim[i];
                       BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta); { zero en principe }
                       BeffMag[i]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
                       {definition des angles théta et phi du champ efficace}
                       if BeffMag[i]<>0 then BeffTheta[i]:=ArcCos(BeffZ/BeffMag[i]) else BeffTheta[i]:=0; {en radians}
                       if (BeffX<>0) and (BeffY<>0) then BeffPhi[i]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[i]:=0;{en radians}
                end;
             end;
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc3); { on fait le calcul de reflectivité }
             MyDataCalc3.Normalise(MyExperimentalParameters.NormalisationFactor);
             { fin du calcul avec PHI = 90° }

             { on trace COS PHI dans le plot du bas  }
             SetLegendXYGraphPhi('COS PHI and SIN² PHI','Cos Phi calc.','Sin²PHI calc.','-','-');
             for i:=0 to MyDataCalc.Abscisses.length-1 do
             begin
                a:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]);
                if (a<-10) or (a>10) then a:=NAN;
                SRGraph1DForm.xyGraphPhi[SerieCOSPHI][MyDataCalc.Abscisses[i]]:=a;
                a:=MyDataCalc.Rud.values[i]/MyDataCalc3.Rud.values[i];
                if (a<-10) or (a>10) then a:=NAN;
                SRGraph1DForm.xyGraphPhi[SerieSIN2PHI][MyDataCalc.Abscisses[i]]:=a;
             end;
             XYGraphPhi_ReleaseUpdate(SerieCOSPHI);XYGraphPhi_ReleaseUpdate(SerieSIN2PHI);
             end;

   MyDataCalc.SaveToClipboard;
   freeIt(R,T);freeIt(Rup,Rdo,Tup,Tdo);freeIt(Ruu,Rdd,Rud,Rdu);freeIt(Tuu,Tdd,Tud,Tdu);
end;

{ calcul de la différence entre la courbe mesurée et la courbe calculée }
{ on plotte la courbe abs(Rexp-Rcalc)/(Rexp-Rcalc) sur le graph XYgraphPhi }
{ INPUT: 100% implicite                                                    }
{ OUTPUT: on plotte la différence des courbes expérimentale et calculées sur le graphPhi }
{         (R-Rexp)/(R+Rexp)                                                              }
{ REMARQUE: IL FAUT AVOIR CHARGE UN FICHIER DE DATA !!!                                  }
procedure TSimulReflecWindow.CalculdifferenceCosPhiSinPhi1Click(Sender: TObject);
var diff,diffSmooth:double;
    fraction1,fraction2:double;
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataExp.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc.abscisses.copy(MyDataExp.abscisses);MyDataCalc.updateWIthAbscisses(MyExperimentalParameters); { mise a jour des abscisses et des resolutions }
   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);

   if PolydomainsMenu.Checked=true
   then begin
        MyMultiLayer2.UpdateFromMultiLayerGrid(MultiLayerGrid2,MyExperimentalParameters);
        MyDataCalc2.abscisses.copy(MyDataExp.abscisses);MyDataCalc2.updateWithAbscisses(MyExperimentalParameters);
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);
        MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
        { normalisation aditionnelle pour le taux de domaines }
        fraction1:=fraction1Box.value/(fraction1Box.value+fraction2Box.value);
        fraction2:=fraction2Box.value/(fraction1Box.value+fraction2Box.value);
        MyDataCalc.Normalise(fraction1);MyDataCalc2.Normalise(fraction2);
        { Addition des réflectivités }
        With MyDataCalc do
          begin R.Add(MyDataCalc2.R);T.Add(MyDataCalc2.T);
              Rup.Add(MyDataCalc2.Rup);Rdo.Add(MyDataCalc2.Rdo);Tup.Add(MyDataCalc2.Tup);Tdo.Add(MyDataCalc2.Tdo);
              Ruu.Add(MyDataCalc2.Ruu);Rdd.Add(MyDataCalc2.Rdd);Rud.Add(MyDataCalc2.Rud);Rdu.Add(MyDataCalc2.Rdu);
              Tuu.Add(MyDataCalc2.Tuu);Tdd.Add(MyDataCalc2.Tdd);Tud.Add(MyDataCalc2.Tud);Tdu.Add(MyDataCalc2.Tdu);
          end;
        end;

   SRGraph1Dform.PlotDifference(MyDataExp,MyDataCalc);
   diff:=difference(MyDataExp,MyDataCalc,MyExperimentalParameters);ecartBox.value:=diff;{ EcartBox.text:=floattostrf(diff,ffgeneral,3,4); }
   if MyMultiLayer.profiled
   then begin diffSmooth:=MyMultiLayer.SmoothProfile(MyProfiles);ecartBoxSmooth.value:=diffSmooth;ecartBox.value:=diff+diffSmooth  end;
   MyDataCalc.SaveToClipboard;
end;


procedure TSimulReflecWindow.PlotExperimentalCosPHIandSinPhi1Click(Sender: TObject);
var  i:integer;
     fraction1,fraction2:double;
     R,T,Rup,Rdo,Tup,Tdo,Ruu,Rdd,Rud,Rdu,Tuu,Tdd,Tud,Tdu:Tvec;
     BeffX,BeffY,BeffZ:double;
begin
   createIt(R,T);createIt(Rup,Rdo,Tup,Tdo);createIt(Ruu,Rdd,Rud,Rdu);createIt(Tuu,Tdd,Tud,Tdu);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataExp.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc.abscisses.copy(MyDataExp.abscisses);
   MyDataCalc2.abscisses.copy(MyDataExp.abscisses);
   MyDataCalc3.abscisses.copy(MyDataExp.abscisses);
   MyDataCalc.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc2.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc3.updateWithAbscisses(MyExperimentalParameters);

   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);

   if (typePolarisation.text='non polarised') or (typePolarisation.text='polarised')
   then begin MessageDlg('You need to use the options ''with spin-flip'' or ''with SF high field', mtInformation, [mbOk], 0);exit; end;

   if typePolarisation.text='with spin-flip'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             { calcul de la reflectivity avec PHI = 0° }
             MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
             for i:=0 to MyMultiLayer2.nbrLayers-1 do MyMultiLayer2.phi[i]:=0;             { on remplace les angles phi par la valeur 0 }
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
             MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
             { fin du calcul avec PHI = 0° }
             { calcul de la reflectivity avec PHI = 90° }
             MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
             for i:=0 to MyMultiLayer2.nbrLayers-2 do MyMultiLayer2.phi[i]:=pi/2;       { on remplace les angles phi par la valeur pi/2 suaf le vide !! }
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc3); { on fait le calcul de reflectivité }
             MyDataCalc3.Normalise(MyExperimentalParameters.NormalisationFactor);
             { fin du calcul avec PHI = 90° }

             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSF);
             { on trace COS PHI dans le plot du bas  }
             SetLegendXYGraphPhi('COS PHI and SIN² PHI','-','-','Cos Phi exp.','Sin²PHI exp.');
             for i:=0 to MyDataExp.Abscisses.length-1 do
             begin
                SRGraph1DForm.xyGraphPhi[SeriePhi3][MyDataExp.Abscisses[i]]:=(MyDataExp.Ruu.values[i]-MyDataExp.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]);
                SRGraph1DForm.xyGraphPhi[SeriePhi4][MyDataExp.Abscisses[i]]:=MyDataExp.Rud.values[i]/MyDataCalc3.Rud.values[i];
             end;
             XYGraphPhi_ReleaseUpdate(SeriePhi3);XYGraphPhi_ReleaseUpdate(SeriePhi4);
             end;
   if typePolarisation.text='with SF high field'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSFUD);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdu,SerieRcalcSFDU);

             { calcul de la reflectivity avec PHI = 0° }
             MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
             for i:=0 to MyMultiLayer2.nbrLayers-1 do
             begin
                with MyMultiLayer2 do
                begin  { calcul du champ effectif dans chaque couche } { avec PHI = 0; on suppose que le champ est suivant PHI=0 }
                       BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi)+Aim[i];
                       BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi); { zero en principe }
                       BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta); { zero en principe }
                       BeffMag[i]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
                       {definition des angles théta et phi du champ efficace}
                       if BeffMag[i]<>0 then BeffTheta[i]:=ArcCos(BeffZ/BeffMag[i]) else BeffTheta[i]:=0; {en radians}
                       if (BeffX<>0) and (BeffY<>0) then BeffPhi[i]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[i]:=0;{en radians}
                end;
             end;
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
             MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
             { fin du calcul avec PHI = 0° }
             { calcul de la reflectivity avec PHI = 90° }
             MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
             for i:=0 to MyMultiLayer2.nbrLayers-2 do       { on remplace les angles phi par la valeur pi/2 suaf le vide !! }
             begin
                with MyMultiLayer2 do
                begin  { calcul du champ effectif dans chaque couche } { avec PHI = 90°; on suppose que le champ est suivant PHI=0 }
                       BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi);
                       BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi)+Aim[i];
                       BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta); { zero en principe }
                       BeffMag[i]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
                       {definition des angles théta et phi du champ efficace}
                       if BeffMag[i]<>0 then BeffTheta[i]:=ArcCos(BeffZ/BeffMag[i]) else BeffTheta[i]:=0; {en radians}
                       if (BeffX<>0) and (BeffY<>0) then BeffPhi[i]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[i]:=0;{en radians}
                end;
             end;
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc3); { on fait le calcul de reflectivité }
             MyDataCalc3.Normalise(MyExperimentalParameters.NormalisationFactor);
             { fin du calcul avec PHI = 90° }

             { on trace COS PHI dans le plot du bas  }
             SetLegendXYGraphPhi('COS PHI and SIN² PHI','-','-','Cos Phi exp.','Sin²PHI exp.');
             for i:=0 to MyDataCalc.Abscisses.length-1 do
             begin
                SRGraph1DForm.xyGraphPhi[SeriePhi3][MyDataCalc.Abscisses[i]]:=(MyDataExp.Ruu.values[i]-MyDataExp.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]);
                SRGraph1DForm.xyGraphPhi[SeriePhi4][MyDataCalc.Abscisses[i]]:=MyDataExp.Rud.values[i]/MyDataCalc3.Rud.values[i];
             end;
             XYGraphPhi_ReleaseUpdate(SeriePhi3);XYGraphPhi_ReleaseUpdate(SeriePhi4);
             end;

   MyDataCalc.SaveToClipboard;
   freeIt(R,T);freeIt(Rup,Rdo,Tup,Tdo);freeIt(Ruu,Rdd,Rud,Rdu);freeIt(Tuu,Tdd,Tud,Tdu);
end;

procedure TSimulReflecWindow.ExperientalSpinAsymmetry1Click(Sender: TObject);
var diff,diffSmooth:double;
    fraction1,fraction2:double;
    i:integer;
begin
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataExp.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc.abscisses.copy(MyDataExp.abscisses);MyDataCalc.updateWithAbscisses(MyExperimentalParameters);

   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);

   if MyDataExp.PolarisationType='polarised'
   then begin
        { plotting de la courbe de différence entre la courbe expérimentale et la courbe calculée }
        SetLegendXYGraphPhi('SPIN ASYMMETRY','-','-','SA exp.','-');
        for i:=0 to MyDataExp.abscisses.length-1 do
        with SimulReflecWindow do
        begin
           SRGraph1DForm.xyGraphPhi[SeriePhi3][MyDataExp.abscisses[i]]:=(MyDataExp.Rup.values[i]-MyDataExp.Rdo.values[i])/(MyDataExp.Rup.values[i]+MyDataExp.Rdo.values[i]);
        end;
        XYGraphPhi_ReleaseUpdate(SeriePhi3);
        end;
   if MyDataExp.PolarisationType='with spin-flip'
   then begin
        { plotting de la courbe de différence entre la courbe expérimentale et la courbe calculée }
        SetLegendXYGraphPhi('SPIN ASYMMETRY','-','-','SA exp.','-');
        for i:=0 to MyDataExp.abscisses.length-1 do
        with SimulReflecWindow do
        begin
           SRGraph1DForm.xyGraphPhi[SeriePhi3][MyDataExp.abscisses[i]]:=(MyDataExp.Ruu.values[i]-MyDataExp.Rdd.values[i])/(MyDataExp.Ruu.values[i]+MyDataExp.Rdd.values[i]);
        end;
        XYGraphPhi_ReleaseUpdate(SeriePhi3);
        end;
   if MyDataExp.PolarisationType='with SF high field'
   then begin
        { plotting de la courbe de différence entre la courbe expérimentale et la courbe calculée }
        SetLegendXYGraphPhi('SPIN ASYMMETRY','-','-','SA exp.','-');
        for i:=0 to MyDataExp.abscisses.length-1 do
        with SimulReflecWindow do
        begin
           SRGraph1DForm.xyGraphPhi[SeriePhi3][MyDataExp.abscisses[i]]:=(MyDataExp.Ruu.values[i]-MyDataExp.Rdd.values[i])/(MyDataExp.Ruu.values[i]+MyDataExp.Rdd.values[i]);
        end;
        XYGraphPhi_ReleaseUpdate(SeriePhi3);
        end;

end;

procedure TSimulReflecWindow.SpinAsymmDifferenceSA1Click(Sender: TObject);
var diff,diffSmooth:double;
    fraction1,fraction2:double;
    i:integer;
begin
   { on copie les dataExp et on les crops }
   MyDataExpFit.clone(MyDataExp);
   MydataExpFit.crop(FitAbsMin.value,FitAbsMax.value);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataExpFit.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc.updateWithAbscisses(MyExperimentalParameters);

   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);

   { fit sur la spin-asymmety uniquement }
   MyDataCalc.R.length:=MyDataCalc.Ruu.length;
   MyDataExpFit.R.length:=MyDataExpFit.Ruu.length;
   for i:=0 to MyDataCalc.R.length-1 do
   begin MyDataCalc.R[i]:=(MyDataCalc.Ruu[i]-MyDataCalc.Rdd[i])/(MyDataCalc.Ruu[i]+MyDataCalc.Rdd[i]);
         MyDataExpFit.R[i]:=(MyDataExpFit.Ruu[i]-MyDataExpFit.Rdd[i])/(MyDataExpFit.Ruu[i]+MyDataExpFit.Rdd[i]);
   end;

   with SRGraph1DForm do
   begin
        SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','SA diff.','SA exp.','-');
        xyGraphPhi.Appearance.graphTitle:='SPIN ASYMMETRY DIFFERENCE';
        for i:=0 to MyDataExpFit.abscisses.length-1 do
        begin
         if MyDataExpFit.R.values[i]<>0   { au cas ou des data manquent }
         then
           with SimulReflecWindow do
           begin
              xyGraphPhi[SeriePhi1][MyDataExpFit.abscisses[i]]:=MyDataCalc.R.values[i];
              xyGraphPhi[SeriePhi3][MyDataExpFit.abscisses[i]]:=MyDataExpFit.R.values[i];
              xyGraphPhi[SeriePhi2][MyDataExpFit.abscisses[i]]:=MyDataExpFit.R.values[i]-MyDataCalc.R.values[i];
           end;
        end;
        XYGraphPhi_ReleaseUpdate(SeriePhi1);XYGraphPhi_ReleaseUpdate(SeriePhi2);XYGraphPhi_ReleaseUpdate(SeriePhi3);
   end;
   diff:=RMS(MyDataExpFit.R,MyDataCalc.R);ecartBox.value:=diff;

   MyDataCalc.SaveToClipboard;
end;

procedure TSimulReflecWindow.CosPHIdifference;
var diff,diffSmooth:double;
    fraction1,fraction2:double;
    i:integer;
    BeffX,BeffY,BeffZ:double;
    a1,a2:double;
begin
   { on copie les dataExp et on les crops }
   MyDataExpFit.clone(MyDataExp);
   MydataExpFit.crop(FitAbsMin.value,FitAbsMax.value);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataExpFit.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc2.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc2.updateWithAbscisses(MyExperimentalParameters);

   if (typePolarisation.text='non polarised') or (typePolarisation.text='polarised')
   then begin MessageDlg('You need to use the options ''with spin-flip'' or ''with SF high field', mtInformation, [mbOk], 0);exit; end;

   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
   MydataCalc.crop(FitAbsMin.value,FitAbsMax.value);

   if typePolarisation.text='with spin-flip'
   then begin
        { calcul de la reflectivity avec PHI = 0° }
        MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
        for i:=0 to MyMultiLayer2.nbrLayers-1 do MyMultiLayer2.phi[i]:=0;             { on remplace les angles phi par la valeur 0 }
        { fin du calcul avec PHI = 0° }
        end;

   if typePolarisation.text='with SF high field'
   then begin
        { calcul de la reflectivity avec PHI = 0° }
        MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
        for i:=0 to MyMultiLayer2.nbrLayers-1 do
             begin
                with MyMultiLayer2 do
                begin  { calcul du champ effectif dans chaque couche } { avec PHI = 0; on suppose que le champ est suivant PHI=0 }
                       BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi)+Aim[i];
                       BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi); { zero en principe }
                       BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta); { zero en principe }
                       BeffMag[i]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
                       {definition des angles théta et phi du champ efficace}
                       if BeffMag[i]<>0 then BeffTheta[i]:=ArcCos(BeffZ/BeffMag[i]) else BeffTheta[i]:=0; {en radians}
                       if (BeffX<>0) and (BeffY<>0) then BeffPhi[i]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[i]:=0;{en radians}
                end;
             end;
        end;

   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
   MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
   MydataCalc2.crop(FitAbsMin.value,FitAbsMax.value);
   MyDataExpFit.R.length:=MyDataExpFit.Ruu.length;
   for i:=0 to MyDataCalc.R.length-1 do
   begin MyDataCalc.R[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]); { calculated cos PHI }
         MyDataExpFit.R[i]:=(MyDataExpFit.Ruu.values[i]-MyDataExpFit.Rdd.values[i])/(MyDataCalc2.Ruu.values[i]-MyDataCalc2.Rdd.values[i]); { experimental COS PHI }
   end;

   with SRGraph1DForm do
   begin
        { on trace COS PHI dans le plot du bas  }
        SetLegendXYGraphPhi('COS PHI difference','Cos Phi calc.','difference','Cos Phi exp.','-');
        for i:=0 to MyDataCalc.Abscisses.length-1 do
        begin
           a1:=MyDataCalc.R[i];if (a1<-10) or (a1>10) then a1:=NAN;
           xyGraphPhi[SeriePhi1][MyDataCalc.Abscisses[i]]:=a1;
           a2:=MyDataExpFit.R[i];if (a2<-10) or (a2>10) then a2:=NAN;
           xyGraphPhi[SeriePhi3][MyDataExpFit.Abscisses[i]]:=a2;
           xyGraphPhi[SeriePhi2][MyDataExpFit.Abscisses[i]]:=a2-a1;
        end;
        XYGraphPhi_ReleaseUpdate(SeriePhi1);XYGraphPhi_ReleaseUpdate(SeriePhi2);XYGraphPhi_ReleaseUpdate(SeriePhi3);
   end;

   diff:=RMS(MyDataExpFit.R,MyDataCalc.R);ecartBox.value:=diff;
   MyDataCalc.SaveToClipboard;
end;

procedure TSimulReflecWindow.CosPHIdifference1Click(Sender: TObject);
var diff,diffSmooth:double;
    fraction1,fraction2:double;
    i:integer;
begin
   CosPhiDifference
end;

procedure TSimulReflecWindow.SinPHIDifference;
var diff,diffSmooth:double;
    fraction1,fraction2:double;
    i:integer;
    BeffX,BeffY,BeffZ:double;
    a1,a2:double;
begin
   { on copie les dataExp et on les crops }
   MyDataExpFit.clone(MyDataExp);
   MydataExpFit.crop(FitAbsMin.value,FitAbsMax.value);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataExpFit.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc.updateWithAbscisses(MyExperimentalParameters);
   MyDataCalc2.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc2.updateWithAbscisses(MyExperimentalParameters);
   
   if (typePolarisation.text='non polarised') or (typePolarisation.text='polarised')
   then begin MessageDlg('You need to use the options ''with spin-flip'' or ''with SF high field', mtInformation, [mbOk], 0);exit; end;

   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
   MydataCalc.crop(FitAbsMin.value,FitAbsMax.value);

   if typePolarisation.text='with spin-flip'
   then begin
        { calcul de la reflectivity avec PHI = 90° }
        MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
        for i:=0 to MyMultiLayer2.nbrLayers-2 do MyMultiLayer2.phi[i]:=pi/2;       { on remplace les angles phi par la valeur pi/2 suaf le vide !! }
        CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
        MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
        MydataCalc2.crop(FitAbsMin.value,FitAbsMax.value);
        { fin du calcul avec PHI = 90° }
        end;

   if typePolarisation.text='with SF high field'
   then begin
        { calcul de la reflectivity avec PHI = 90° }
        MyMultiLayer2.clone(MyMultiLayer);                                         { on fait une copie du système }
        for i:=0 to MyMultiLayer2.nbrLayers-2 do       { on remplace les angles phi par la valeur pi/2 suaf le vide !! }
             begin
                with MyMultiLayer2 do
                begin  { calcul du champ effectif dans chaque couche } { avec PHI = 90°; on suppose que le champ est suivant PHI=0 }
                       BeffX:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Cos(MyExperimentalParameters.fieldPhi);
                       BeffY:=MyExperimentalParameters.FieldMag*Sin(MyExperimentalParameters.fieldTheta)*Sin(MyExperimentalParameters.fieldPhi)+Aim[i];
                       BeffZ:=MyExperimentalParameters.FieldMag*Cos(MyExperimentalParameters.fieldTheta); { zero en principe }
                       BeffMag[i]:= sqrt(sqr(BeffX)+sqr(BeffY)+sqr(BeffZ));
                       {definition des angles théta et phi du champ efficace}
                       if BeffMag[i]<>0 then BeffTheta[i]:=ArcCos(BeffZ/BeffMag[i]) else BeffTheta[i]:=0; {en radians}
                       if (BeffX<>0) and (BeffY<>0) then BeffPhi[i]:=arg(Cplx(BeffX,BeffY)) else BeffPhi[i]:=0;{en radians}
                end;
             end;
        { fin du calcul avec PHI = 90° }
        end;

   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2); { on fait le calcul de reflectivité }
   MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor);
   MydataCalc2.crop(FitAbsMin.value,FitAbsMax.value);
   MyDataExpFit.R.length:=MyDataExpFit.Ruu.length;
   for i:=0 to MyDataCalc.R.length-1 do
        begin MyDataCalc.R[i]:=MyDataCalc.Rud.values[i]/MyDataCalc2.Rud.values[i]; { calculated SIN² PHI }
              MyDataExpFit.R[i]:=MyDataExpFit.Rud.values[i]/MyDataCalc2.Rud.values[i]; { experimental SIN² PHI }
        end;

   with SRGraph1DForm do
        begin
                { on trace SIN²PHI dans le plot du bas  }
                SetLegendXYGraphPhi('SIN² PHI difference','Sin²Phi calc.','difference','Sin²Phi exp.','-');
                for i:=0 to MyDataCalc.Abscisses.length-1 do
                begin
                     a1:=MyDataCalc.R[i];if (a1<-10) or (a1>10) then a1:=NAN;
                     xyGraphPhi[SeriePhi1][MyDataCalc.Abscisses[i]]:=a1;
                     a2:=MyDataExpFit.R[i];if (a2<-10) or (a2>10) then a2:=NAN;
                     xyGraphPhi[SeriePhi3][MyDataExpFit.Abscisses[i]]:=a2;
                     xyGraphPhi[SeriePhi2][MyDataExpFit.Abscisses[i]]:=a2-a1;
                end;
        XYGraphPhi_ReleaseUpdate(SeriePhi1);XYGraphPhi_ReleaseUpdate(SeriePhi2);XYGraphPhi_ReleaseUpdate(SeriePhi3);
        end;

   diff:=RMS(MyDataExpFit.R,MyDataCalc.R);ecartBox.value:=diff;
   MyDataCalc.SaveToClipboard;
end;

procedure TSimulReflecWindow.SinPHIDifference1Click(Sender: TObject);
begin
    SinPHIDifference;
end;

procedure TSimulReflecWindow.TestButtonClick(Sender: TObject);
var  i:integer;
     fraction1,fraction2:double;
     R,T,Rup,Rdo,Tup,Tdo,Ruu,Rdd,Rud,Rdu,Tuu,Tdd,Tud,Tdu,SA,SAExp:Tvec;
begin
   createIt(R,T);createIt(Rup,Rdo,Tup,Tdo);createIt(Ruu,Rdd,Rud,Rdu);createIt(Tuu,Tdd,Tud,Tdu);
   createIt(SA,SAexp);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataCalc.updateWithRange(MyExperimentalParameters);
   
   if typePolarisation.text='polarised'
   then if polydomainsMenu.checked=false
        then begin
             for i:=1 to 1000 do CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,'Rup');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,'Rdo');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tup,'Tup');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdo,'Tdo');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,SerieRcalcDO);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','SA exp','-');
             SA.Copy(MyDataCalc.Rup);SAexp.Copy(MyDataExp.Rup);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Rup.values[i]-MyDataCalc.Rdo.values[i])/(MyDataCalc.Rup.values[i]+MyDataCalc.Rdo.values[i]);
             for i:=0 to MyDataExp.Abscisses.length-1 do SAexp[i]:=(MyDataExp.Rup.values[i]-MyDataExp.Rdo.values[i])/(MyDataExp.Rup.values[i]+MyDataExp.Rdo.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             SRGraph1DForm.TransferCurvePhi(MyDataExp.Abscisses,SAExp,3);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);XYGraphPhi_ReleaseUpdate(3);
             end
end;

{ procedure de multiplication de la courbe de reflectivité par Q4               }
procedure TSimulReflecWindow.RxQ4(R,Q,RQ4:Tvec);
var i,nbrPoints:integer;
begin
  for i:=0 to R.length-1 do RQ4.values[i]:=R.values[i]*sqr(sqr(Q.values[i]));
end;

{ plot de la réflectivité multipliée par le vecteur de diffusion à la puissance 4 }
{ pour suivre la loi de Porod                                                   }
procedure TSimulReflecWindow.RxQ41Click(Sender: TObject);
var  i:integer;
     fraction1,fraction2:double;
     R,T,Rup,Rdo,Tup,Tdo,Ruu,Rdd,Rud,Rdu,Tuu,Tdd,Tud,Tdu,SA,SAExp:Tvec;
begin
   createIt(R,T);createIt(Rup,Rdo,Tup,Tdo);createIt(Ruu,Rdd,Rud,Rdu);createIt(Tuu,Tdd,Tud,Tdu);
   createIt(SA,SAexp);
   { mise a jour des paramètres experimentaux }
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   MyDataCalc.updateWithRange(MyExperimentalParameters);

   If polydomainsMenu.checked=true
   then begin
        MyMultiLayer2.UpdateFromMultiLayerGrid(MultiLayerGrid2,MyExperimentalParameters);
        MyDataCalc2.updateWithRange(MyExperimentalParameters);
        fraction1:=fraction1Box.value/(fraction1Box.value+fraction2Box.value);
        fraction2:=fraction2Box.value/(fraction1Box.value+fraction2Box.value);
        end;

{   with MyDataCalc do }
   begin
   if typePolarisation.text='non polarised'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);

             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.R,SerieRcalcUP);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.R,'R');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.T,'T');
        {        Graph2DForm.transferCurve(Angles,T,SerieRcalcDO); }
             end
        else begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
             R.copy(MyDataCalc.R);R.Add(MyDataCalc2.R);T.copy(MyDataCalc.T);R.Add(MyDataCalc2.T);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,R,SerieRcalcUP);
             Transfer1DCurve(MyDataCalc.Abscisses,R,'R');
             Transfer1DCurve(MyDataCalc.Abscisses,T,'T');
             end;

   if typePolarisation.text='polarised'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,'Rup');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,'Rdo');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tup,'Tup');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdo,'Tdo');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rup,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdo,SerieRcalcDO);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','SA exp','-');
             SA.Copy(MyDataCalc.Rup);SAexp.Copy(MyDataExp.Rup);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Rup.values[i]-MyDataCalc.Rdo.values[i])/(MyDataCalc.Rup.values[i]+MyDataCalc.Rdo.values[i]);
             for i:=0 to MyDataExp.Abscisses.length-1 do SAexp[i]:=(MyDataExp.Rup.values[i]-MyDataExp.Rdo.values[i])/(MyDataExp.Rup.values[i]+MyDataExp.Rdo.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             SRGraph1DForm.TransferCurvePhi(MyDataExp.Abscisses,SAExp,3);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);XYGraphPhi_ReleaseUpdate(3);
             end
        else begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
             Rup.copy(MyDataCalc.Rup);Rup.Add(MyDataCalc2.Rup);Rdo.copy(MyDataCalc.Rdo);Rdo.Add(MyDataCalc2.Rdo);
             Tup.copy(MyDataCalc.Tup);Tup.Add(MyDataCalc2.Tup);Tdo.copy(MyDataCalc.Tdo);Tdo.Add(MyDataCalc2.Tdo);

             Transfer1DCurve(MyDataCalc.Abscisses,Rup,'Rup');Transfer1DCurve(MyDataCalc.Abscisses,Rdo,'Rdo');
             Transfer1DCurve(MyDataCalc.Abscisses,Tup,'Tup');Transfer1DCurve(MyDataCalc.Abscisses,Tdo,'Tdo');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rup,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdo,SerieRcalcDO);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Rup);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Rup.values[i]-MyDataCalc.Rdo.values[i])/(MyDataCalc.Rup.values[i]+MyDataCalc.Rdo.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   if typePolarisation.text='with spin-flip'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSF);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end
        else begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
             Ruu.copy(MyDataCalc.Ruu);Ruu.Add(MyDataCalc2.Ruu);Rdd.copy(MyDataCalc.Rdd);Rdd.Add(MyDataCalc2.Rdd);Rud.copy(MyDataCalc.Rud);Rud.Add(MyDataCalc2.Rud);
             Tuu.copy(MyDataCalc.Tuu);Tuu.Add(MyDataCalc2.Tuu);Tdd.copy(MyDataCalc.Tdd);Tdd.Add(MyDataCalc2.Tdd);Tud.copy(MyDataCalc.Tud);Tud.Add(MyDataCalc2.Tud);

             Transfer1DCurve(MyDataCalc.Abscisses,Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rud,SerieRcalcSF);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   if typePolarisation.text='with SF high field'
   then if polydomainsMenu.checked=false
        then begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
             MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,MyDataCalc.Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSFUD);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdu,SerieRcalcSFDU);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end
        else begin
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor*fraction1);
             CalculateReflectivity(MyExperimentalParameters,MyMultiLayer2,MyDataCalc2);MyDataCalc2.Normalise(MyExperimentalParameters.NormalisationFactor*fraction2);
             Ruu.copy(MyDataCalc.Ruu);Ruu.Add(MyDataCalc2.Ruu);Rdd.copy(MyDataCalc.Rdd);Rdd.Add(MyDataCalc2.Rdd);Rud.copy(MyDataCalc.Rud);Rud.Add(MyDataCalc2.Rud);
             Tuu.copy(MyDataCalc.Tuu);Tuu.Add(MyDataCalc2.Tuu);Tdd.copy(MyDataCalc.Tdd);Tdd.Add(MyDataCalc2.Tdd);Tud.copy(MyDataCalc.Tud);Tud.Add(MyDataCalc2.Tud);

             Transfer1DCurve(MyDataCalc.Abscisses,Ruu,'Ruu');Transfer1DCurve(MyDataCalc.Abscisses,Rdd,'Rdd');Transfer1DCurve(MyDataCalc.Abscisses,Rud,'Rsf');
             Transfer1DCurve(MyDataCalc.Abscisses,Tuu,'Tuu');Transfer1DCurve(MyDataCalc.Abscisses,Tdd,'Tdd');Transfer1DCurve(MyDataCalc.Abscisses,Tud,'Tsf');
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Ruu,SerieRcalcUP);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,Rdd,SerieRcalcDO);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rud,SerieRcalcSFUD);
             SRGraph1DForm.transferCurve(MyDataCalc.Abscisses,MyDataCalc.Rdu,SerieRcalcSFDU);
             { on rajoute la spin asymmetrie dans le graph du bas }
             SetLegendXYGraphPhi('SPIN ASYMMETRY','SA calc.','-','-','-');
             SA.Copy(MyDataCalc.Ruu);
             for i:=0 to MyDataCalc.Abscisses.length-1 do SA[i]:=(MyDataCalc.Ruu.values[i]-MyDataCalc.Rdd.values[i])/(MyDataCalc.Ruu.values[i]+MyDataCalc.Rdd.values[i]);
             SRGraph1DForm.TransferCurvePhi(MyDataCalc.Abscisses,SA,SeriePhaseUP);
             XYGraphPhi_ReleaseUpdate(SeriePhaseUP);
             end;
   end;
   MyDataCalc.SaveToClipboard;
   freeIt(R,T);freeIt(Rup,Rdo,Tup,Tdo);freeIt(Ruu,Rdd,Rud,Rdu);freeIt(Tuu,Tdd,Tud,Tdu);freeIt(SA);
end;

{ INTERFACE WITH EMMANUEL PROGRAM }
{ execution du programme PNR de Emmanuel Kentzinger }
procedure TSimulReflecWindow.StartPNRbuttonClick(Sender: TObject);
begin
  { lancement du calcul }
  chdir(SourceDirectory+'pnr'); 
  JvCreateProcess1.CommandLine:=SourceDirectory+'pnr\pnr.exe';
  JvCreateProcess1.Run;
end;

{ lecture des data dans des spectres 1D }
procedure TSimulReflecWindow.LoadCalcButtonClick(Sender: TObject);
begin
  ReadPNRfile(SourceDirectory+'pnr\simulation','PNR_sim_');
end;


{ lecture des data expérimentales }
procedure TSimulReflecWindow.LoadDataButtonClick(Sender: TObject);
begin
  ReadPNRfile(SourceDirectory+'pnr\pnr.dat','PNR_dat_');
end;


{ ecriture du fichier d'enre de pnr }
{ conversion : N.bM = gn µn µ0 M * m / 2 pi hb²   }
procedure TSimulReflecWindow.ExportParametersButtonClick(Sender: TObject);
const cste = mun/Pihm;
var i,j:integer;
  F:textFile;
  valeur:cardinal;
  Xsize,Ysize:integer;
  vind:integer;
  s:string;
  ntop,nbot,nML:integer;
begin
    MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
    AssignFile(F, SourceDirectory+'pnr\fit_pnr_mult.ent');Rewrite(F); { Fichier sélectionné dans la boîte de dialogue }
    writeln(F,FloatToStr(Slit1Box.value));
    writeln(F,FloatToStr(Slit2Box.value));
    writeln(F,FloatToStr(SampleLengthBox.value));
    writeln(F,FloatToStr(D1Box.value));
    writeln(F,FloatToStr(D2Box.value));
    writeln(F,'');

    writeln(F,BaseNameBox.text+'.uu.ref');
    writeln(F,NptsBox.value);
    writeln(F,BaseNameBox.text+'.dd.ref');
    writeln(F,NptsBox.value);
    writeln(F,BaseNameBox.text+'.ud.ref');
    writeln(F,NptsBox.value);
    writeln(F,BaseNameBox.text+'.du.ref');
    writeln(F,NptsBox.value);
    writeln(F,'');

    writeln(F,FloatToStr(lambdaBox.value*10));
    writeln(F,FloatToStr(dLambdaBox.value*10));
    writeln(F,'');

    { description de la multicouche }
    { deux cas à traiter : multicoche ou pas mutlicouche }
{    with MyMultilayer do }
    begin
      If not MyMultilayer.MLSystem
      then begin { mulitcouche simple }
           writeln(F,'0'); { pas de couche au-dessus de la ML }
           writeln(F,'');

           writeln(F,IntToStr(MyMultilayer.NbrLayers-2)); { on met les couches dans la ML  }
           writeln(F,'');
           for i:=MyMultilayer.NbrLayers-2 to 1 do { la couche de vide n'est pas décrite }
           begin
             writeln(F,FloatToStr(MyMultilayer.z[i]*1e10)); { thickness in (A) }
             writeln(F,FloatToStr(MyMultilayer.d[i]*MyMultilayer.bn[i]*1e-14)); { real part of nuclear scattering length density Nb'  (in A**-2) *1e6 }
             writeln(F,FloatToStr(MyMultilayer.d[i]*MyMultilayer.bni[i]*1e-14)); { imaginary part of nuclear scattering length density Nb'' (in A**-2) *1e6 }
             writeln(F,FloatToStr(-mun/Pihm*MyMultilayer.Aim[i]*1e-14));  { magnetic scattering length density Np (in A**-2) *1e6 }
             writeln(F,FloatToStr(MyMultilayer.theta[i]*180/pi)); { (0 on z, 90 on x-y plane) }
             writeln(F,FloatToStr(MyMultilayer.phi[i]*180/pi));  { (0 on z, 90 on x-y plane) }
             writeln(F,FloatToStr(MyMultilayer.sigma[i]*1e10)); { (0 on x, 90 on y) }
             writeln(F,'');
           end;
           writeln(F,1); { on répète ce motif 1 fois seuelement }
           writeln(F,'');

           writeln(F,0); { pas de couche sous la ML }
           writeln(F,'');
           end
      else begin { cas d'un super-réseau }
           { on va scanner les couches en partant du haut }

           { couches au-dessus du super-réseau }
           i:=MyMultilayer.NbrLayers-2; { indice de la couche du dessus }
           ntop:=0;
           while MyMultilayer.MLYN[i]=-1 do begin dec(i);inc(ntop); end; { combien de couche au-dessus de la ML ? }
           writeln(F,ntop); { pas de couche au-dessus de la ML }
           writeln(F,'');
           if ntop>0 then
             for i:=MyMultilayer.NbrLayers-2 downto MyMultilayer.NbrLayers-2-ntop+1 do
             begin
               writeln(F,FloatToStr(MyMultilayer.z[i]*1e10)); { thickness in (A) }
               writeln(F,FloatToStr(MyMultilayer.d[i]*MyMultilayer.bn[i]*1e-14)); { real part of nuclear scattering length density Nb'  (in A**-2) *1e6 }
               writeln(F,FloatToStr(MyMultilayer.d[i]*MyMultilayer.bni[i]*1e-14)); { imaginary part of nuclear scattering length density Nb'' (in A**-2) *1e6 }
               writeln(F,FloatToStr(-mun/Pihm*MyMultilayer.Aim[i]*1e-14));  { magnetic scattering length density Np (in A**-2) *1e6 }
               writeln(F,FloatToStr(MyMultilayer.theta[i]*180/pi)); { (0 on z, 90 on x-y plane) }
               writeln(F,FloatToStr(MyMultilayer.phi[i]*180/pi));  { (0 on z, 90 on x-y plane) }
               writeln(F,FloatToStr(MyMultilayer.sigma[i]*1e10)); { (0 on x, 90 on y) }
               writeln(F,'');
             end;

           { motif de la multicouche }
           nML:=0;
           while MyMultilayer.MLYN[i]=0 do begin dec(i);inc(nML);end; { combien de couche dans la ML ? }
           writeln(F,nML); { pas de couche au-dessus de la ML }
           writeln(F,'');

           for i:=MyMultilayer.NbrLayers-2-ntop downto MyMultilayer.NbrLayers-2-ntop-nML+1 do { la couche de vide n'est pas décrite }
           begin
             writeln(F,FloatToStr(MyMultilayer.z[i]*1e10)); { thickness in (A) }
             writeln(F,FloatToStr(MyMultilayer.d[i]*MyMultilayer.bn[i]*1e-14)); { real part of nuclear scattering length density Nb'  (in A**-2) *1e6 }
             writeln(F,FloatToStr(MyMultilayer.d[i]*MyMultilayer.bni[i]*1e-14)); { imaginary part of nuclear scattering length density Nb'' (in A**-2) *1e6 }
             writeln(F,FloatToStr(-mun/Pihm*MyMultilayer.Aim[i]*1e-14));  { magnetic scattering length density Np (in A**-2) *1e6 }
             writeln(F,FloatToStr(MyMultilayer.theta[i]*180/pi)); { (0 on z, 90 on x-y plane) }
             writeln(F,FloatToStr(MyMultilayer.phi[i]*180/pi));  { (0 on z, 90 on x-y plane) }
             writeln(F,FloatToStr(MyMultilayer.sigma[i]*1e10)); { (0 on x, 90 on y) }
             writeln(F,'');
           end;
           writeln(F,MyExperimentalParameters.nbrML); { on répète ce motif 1 fois seuelement }
           writeln(F,'');

           nBot:=MyMultilayer.NbrLayers-2-nTop-nML;
           writeln(F,nBot); { pas de couche au-dessus de la ML }
           writeln(F,'');

           { couches sous le superréseau }
           for i:=MyMultilayer.NbrLayers-2-ntop-nML downto MyMultilayer.NbrLayers-2-ntop-nML-nBot+1 do { la couche de vide n'est pas décrite }
           begin
             writeln(F,FloatToStr(MyMultilayer.z[i]*1e10)); { thickness in (A) }
             writeln(F,FloatToStr(MyMultilayer.d[i]*MyMultilayer.bn[i]*1e-14)); { real part of nuclear scattering length density Nb'  (in A**-2) *1e6 }
             writeln(F,FloatToStr(MyMultilayer.d[i]*MyMultilayer.bni[i]*1e-14)); { imaginary part of nuclear scattering length density Nb'' (in A**-2) *1e6 }
             writeln(F,FloatToStr(-mun/Pihm*MyMultilayer.Aim[i]*1e-14));  { magnetic scattering length density Np (in A**-2) *1e6 }
             writeln(F,FloatToStr(MyMultilayer.theta[i]*180/pi)); { (0 on z, 90 on x-y plane) }
             writeln(F,FloatToStr(MyMultilayer.phi[i]*180/pi));  { (0 on z, 90 on x-y plane) }
             writeln(F,FloatToStr(MyMultilayer.sigma[i]*1e10)); { (0 on x, 90 on y) }
             writeln(F,'');
           end;
           end;

    { description du substrat }
    writeln(F,FloatToStr(MyMultilayer.d[0]*MyMultilayer.bn[0]*1e-14)); { real part of nuclear scattering length density Nb'  (in A**-2) *1e6 }
    writeln(F,FloatToStr(MyMultilayer.d[0]*MyMultilayer.bni[0]*1e-14)); { imaginary part of nuclear scattering length density Nb'' (in A**-2) *1e6 }
    writeln(F,FloatToStr(-mun/Pihm*MyMultilayer.Aim[0]*1e-14));  { magnetic scattering length density Np (in A**-2) *1e6 }
    writeln(F,FloatToStr(MyMultilayer.theta[0]*180/pi)); { (0 on z, 90 on x-y plane) }
    writeln(F,FloatToStr(MyMultilayer.phi[0]*180/pi));  { (0 on z, 90 on x-y plane) }
    writeln(F,FloatToStr(MyMultilayer.sigma[0]*1e10)); { (0 on x, 90 on y) }
    writeln(F,'');

    end;

    writeln(F,FloatToStr(scalingFactorBox.value));
    writeln(F,FloatToStr(backgroundBox.value));
    writeln(F,'');

    writeln(F,FloatToStr(PolarizerEffBox.value));
    writeln(F,FloatToStr(AnalyzerEffBox.value));
    writeln(F,FloatToStr(Flipper1EffBox.value));
    writeln(F,FloatToStr(Flipper2EffBox.value));
    writeln(F,'');

    writeln(F,'0');
    writeln(F,'');

{ description des paramètres à fitter   }
{ on laisse flotter pour le moment      }
    writeln(F,'4');
    writeln(F,'2  9 11  16');
    writeln(F,'');

    writeln(F,'1');
    writeln(F,'2');
    writeln(F,'2 16');
    writeln(F,'');

    writeln(F,'0.001');
    writeln(F,'1');
    writeln(F,'');

    writeln(F,'2');
    writeln(F,'1 15');
    writeln(F,'');

    CloseFile(F);
end;

{ fit utilisant la méthode Differential evolution }
procedure TSimulReflecWindow.Differentialevolution1Click(Sender: TObject);
var i:integer;
    t0:TdateTime;
begin
{   SRGraph1DForm.storeCurves; }
   MyDataExpFit.clone(MyDataExp);
   MydataExpFit.crop(FitAbsMin.value,FitAbsMax.value);
   { mise a jour des paramètres experimentaux a partir des informations de la fenetre graphique}
   UpdateVarExperimentalParameters(MyExperimentalParameters);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);

   MyProfiles.update(ProfilesGrid);
   { mise a jour des paramètres de la multicouche a partir de la grille }
   MyMultiLayer.UpdateFromMultiLayerGrid(MultiLayerGrid,MyExperimentalParameters);
   { mise a jour des resolutions expérimentales }
   MyDataExpFit.updateWithAbscisses(MyExperimentalParameters);
   { on crée le spectre des data calculées }
   MyDataCalc.abscisses.copy(MyDataExpFit.abscisses);MyDataCalc.updateWithAbscisses(MyExperimentalParameters); { mise a jour des paramètres de résolution }

   { on affiche le panneau de fit }
   TabSheetFitting.Tabvisible:=true;PageControl.update;

   t0:=time;
   Minimisation_DifferentialEvolution(MyExperimentalParameters,MyMultiLayer,MyDataExpFit,MyDataCalc);
{   if TypePolarisation.text='non polarised' then  MinimisationCrawling(0,MyExperimentalParameters,MyMultiLayer,MyProfiles,MyDataExpFit,MyDataCalc);
   if TypePolarisation.text='polarised' then  MinimisationCrawling_P(0,MyExperimentalParameters,MyMultiLayer,MyProfiles,MyDataExpFit,MyDataCalc);
   if TypePolarisation.text='with spin-flip' then  MinimisationCrawling_SF(0,MyExperimentalParameters,MyMultiLayer,MyProfiles,MyDataExpFit,MyDataCalc);
   if TypePolarisation.text='with SF high field' then  MinimisationCrawling_SF_HF(0,MyExperimentalParameters,MyMultiLayer,MyProfiles,MyDataExpFit,MyDataCalc); }

{ affichage des résultats }
   { mise a jour des courbes }
   CalculateReflectivity(MyExperimentalParameters,MyMultiLayer,MyDataCalc);
   MyDataCalc.Normalise(MyExperimentalParameters.NormalisationFactor);

{ cas particulier éventuel d'un fit de data mesurées en neutrons non polarisés sur un échantillon magnétique }
   if dataFittingOptionsBox.itemIndex=3
   then begin
        { il faut sommer MyDataCalc.Rup et Rdo }
        MyDataCalc.R.length:=MyDataCalc.Rup.length;
        for i:=0 to MyDataCalc.R.length-1 do
           begin MyDataCalc.R[i]:=(MyDataCalc.Rup[i]+MyDataCalc.Rdo[i])/2;
                 MyDataCalc.Rup[i]:=MyDataCalc.R[i];MyDataCalc.Rdo[i]:=MyDataCalc.R[i]; end;
        end;

   SRGraph1Dform.PlotDifference(MyDataExp,MyDataCalc);
   FittingStatus.caption:='Idle';FittingStatus.update;
   IterCrt.caption:='...';IterCrt.update;
   ecartBox.value:=difference(MyDataExpFit,MyDataCalc,MyExperimentalParameters);
   if MyMultiLayer.profiled then begin ecartBoxSmooth.value:=MyMultiLayer.SmoothProfile(MyProfiles);ecartBox.value:=ecartBox.value+ecartBoxSmooth.value end;

   { cas particulier d'un fit sur le Cos PHI }
   if ((TypePolarisation.text='with spin-flip') or (TypePolarisation.text='with SF high field')) and (dataFittingOptionsBox.itemIndex=5) then CosPhiDifference;
   if ((TypePolarisation.text='with spin-flip') or (TypePolarisation.text='with SF high field')) and (dataFittingOptionsBox.itemIndex=6) then SinPhiDifference;

   ElapsedTimeBox.Value:=(time-t0)*86400;
   MyDataCalc.SaveToClipboard;
   PlayWave('The_Fit_Is_Finished');
end;



procedure TSimulReflecWindow.ReplotButtonClick(Sender: TObject);
begin
   ReplotFlag:=true;
end;

end.




