Fitowanie metodą lorentza.

0

Witam.
Muszę napisać program który robi fitowanie metodą lorentza. Dokładniej mówiąc, wczytuję dane z pliku, prosto do wykresu i następnie przeprowadzam fitowanie. Po fitowaniu otrzymuję krzywą na wykresie, plus parametry fitowania.
Utknąłem na samym fitowaniu. Nie wiem jak się za to zabrać.

Pomoże ktoś?

Pozdrawiam.

0

Generalnie musi to być program, który ma dwie opcje. Pierwsza, to symulacja krzywej i fitowanie. Druga, wprowadzenie gotowych danych i do tego fitowanie. Pierwszą opcję mam zrobioną.

Symulacja:

 
procedure TForm2.Button1Click(Sender: TObject);
var
        i:integer;
begin
  Form1.Button1.Enabled:=true;
  II:=StrToFloat(Edit1.Text);
  x0:=StrToFloat(Edit2.Text);
  gamma:=StrToFloat(Edit3.Text);
  stat:=StrToFloat(Edit4.Text)*1e6;
  Series1.Clear;
  with form3 do
  begin
   n:=StrToInt(form2.Edit5.Text);
   for i:=0 to n do
   begin 
       xx[i]:=i; yy[i]:=II*gamma/pi/(sqr(xx[i]-x0)+sqr(gamma));
   Form2.Series1.AddXY(xx[i],yy[i]);

   end;
  end;
end;

Wczytywanie danych z pliku:

procedure TForm2.Button2Click(Sender: TObject);
 Var
  Dane:TextFile;
  X,Y:Real;
begin
  with form3 do
  if OpenDialog1.Execute then
  Series2.Clear;
  AssignFile(Dane, OpenDialog1.FileName);
  Reset(Dane);

  While Not Eof(Dane) Do
 Begin
    Readln(Dane, X, Y);
    Form2.Series2.AddXY(X, Y);
 End;
  CloseFile(Dane);
end;
 

Fitowanie:

 
function TForm3.Li(i:integer;u,v,w:Real):Real;
begin
 Result:=u*w/pi/(sqr(form2.xx[i]-v)+sqr(w));
end;

function TForm3.Lip(i:integer;v,w:Real):Real;
begin
 Result:=w/pi/(sqr(form2.xx[i]-v)+sqr(w));
end;

function TForm3.f1:Real;
var i:integer; licz,mian:Real;
begin
 Result:=0;
 licz:=0; mian:=0;
 for i:=0 to n do
 begin
  licz:= licz+lip(i,v,w)*form2.yy[i]/abs(form2.yy[i]);    
  mian:=mian+sqr(Lip(i,v,w))/abs(form2.yy[i]);
     Result:=licz/mian;               
 end;
end;

function TForm3.f2(v:Real):Real;
var i:integer;
begin
 Result:=0;
 for i:=0 to n do
 begin
 Result:=Result+(Li(i,u,v,w)-form2.yy[i])
 /abs(form2.yy[i])*
            sqr(Li(i,u,v,w))*(form2.xx[i]-v);
 end;
end;

function TForm3.f3(w:Real):Real;
var i:integer;
begin
 Result:=0;
 for i:=0 to n do
begin
 Result:=Result+(Li(i,u,v,w)-form2.yy[i])
 /abs(form2.yy[i])*sqr(Li(i,u,v,w));
 end;
end;

function TForm3.funk2(v:Real):Real;
begin
  Result:=0;
  if row_stycz(funk3,f3,wStart,w)then  //wyznaczenie v -> x0(funk2,u)
  Result:=f2(v);
  wStart:=w;
end;

function TForm3.funk3(w:Real):Real;
begin
 u:=f1;
 Result:=f3(w);
 uStart:=u;
end;


procedure TForm3.Fit;
var
        i:integer; chi2,r1,r2:Real;
begin
  if row_stycz(funk2,f2,vStart,v)then
     //Rozwiązywanie równania Funk1[u,v(Funk2,u)]
  begin
   Edit1.text:=FloatToStr(u);
   Edit2.text:=FloatToStr(v);
   Edit3.text:=FloatToStr(w);
   Series1.Clear;
   Series2.Clear;
   chi2:=0;
   for i:=0 to n do
   begin
    r1:=Form2.YY[i]; r2:=u*w/pi/(sqr(Form2.xx[i]-v)+sqr(w));
    Series1.AddXY(Form2.XX[i],r1);
    Series2.AddXY(Form2.XX[i],r2);


   chi2:=chi2+sqr(r2-r1)/abs(r1);      

   end;
   chi2:=chi2/(n-3);
   Edit7.Text:=FloatToStr(chi2);
  end else ShowMessage('Brak rozwiązania');
end;


0

Wczytywanie pliku trochę niedopatrzone:

procedure TForm2.Button2Click(Sender: TObject);
 Var
  Dane:TextFile;
  X,Y:Real;
begin
  with form3 do
  if OpenDialog1.Execute then
  Series2.Clear;
  AssignFile(Dane, OpenDialog1.FileName);
  Reset(Dane);
 
  While Not Eof(Dane) Do
 Begin
    Readln(Dane, X, Y);
    Form2.Series2.AddXY(X, Y);
 End;
  CloseFile(Dane);
end;

bo bez względu na to, czy wybierzesz plik przez OpenDialog1 czy nie i tak program będzie chciał otworzyć plik o nazwie OpenDialog1.FileName, a to błąd; Jak nie wybierzesz pliku to spowodujesz AV; Prawidłowy kod powinien wyglądać tak:

procedure TForm2.Button2Click(Sender: TObject);
var
  Dane: TextFile;
  X,Y: Real;
begin
  with Form3 do
    begin
      if OpenDialog1.Execute() then
        begin
          Series2.Clear();
          AssignFile(Dane, OpenDialog1.FileName);

          try
            Reset(Dane);

            while not EoF(Dane) do
              begin
                ReadLn(Dane, X, Y);
                Form2.Series2.AddXY(X, Y);
              end;
          finally
            CloseFile(Dane);
          end;
        end;
    end;
end;

To na razie tyle;

0

A no racja. Wcześniej pojawiał mi się błąd. Teraz działa dobrze. Póki co, dzięki ;)

0

Dobra. Mam inny problem/pytanie.
Otwieram plik pomiarowy (.txt) i wprowadzam go na wykres. Ale jak zrobić żeby potem kolejne linijki pomiarów z pliku tekstowego podstawiał do wzorów fitowania?

 
unit Pomiarowe;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Styczne, ExtCtrls, TeeProcs, TeEngine, Chart, StdCtrls, Series, Symulacja;
type
  Wektor=array[0..1000] of Real;
type
  TForm4 = class(TForm)
    OpenDialog1: TOpenDialog;
    Chart1: TChart;
    Button1: TButton;
    Series1: TPointSeries;
    Series2: TLineSeries;
    Button2: TButton;
    GroupBox1: TGroupBox;
    Panel1: TPanel;
    Edit1: TEdit;
    Panel2: TPanel;
    Edit2: TEdit;
    Panel3: TPanel;
    Edit3: TEdit;
    Panel7: TPanel;
    Edit7: TEdit;
    GroupBox2: TGroupBox;
    Panel5: TPanel;
    Edit5: TEdit;
    Panel6: TPanel;
    Edit6: TEdit;
    Button3: TButton;
    Label2: TLabel;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    u,v,w,uStart,vStart,wStart:Real;
    n:integer;
    x,y:Wektor;
    //function funk1(u:Real):Real;
    function funk2(v:Real):Real;
    function funk3(w:Real):Real;
    function f1:Real;
    function f2(v:Real):Real;
    function f3(w:Real):Real;
    function Li(i:integer;u,v,w:Real):Real;
    function Lip(i:integer;v,w:Real):Real;
    procedure Fit;
  end;

var
  Form4: TForm4;

implementation
{$R *.DFM}

procedure TForm4.Button1Click(Sender: TObject);
var
  Dane: TextFile;
begin
  with Form4 do
    begin
      if OpenDialog1.Execute then
        begin
          Series1.Clear;
          AssignFile(Dane, OpenDialog1.FileName);
          
          try
            Reset(Dane);

            while not EoF(Dane) do
              begin
                Readln(Dane, x[n], y[n]);
                Form4.Series1.AddXY(x[n], y[n]);
              end;
          finally
          CloseFile(Dane);
          end;
        end;
    end;
end;




function TForm4.Li(i:integer;u,v,w:Real):Real;
begin
 Result:=u*w/pi/(sqr(X[n]-v)+sqr(w));
end;

function TForm4.Lip(i:integer;v,w:Real):Real;
begin
 Result:=w/pi/(sqr(X[n]-v)+sqr(w));
end;

function TForm4.f1:Real;
var i:integer; licz,mian:Real;
begin
 Result:=0;
 licz:=0; mian:=0;
 for i:=0 to n do
 begin
  licz:= licz+lip(i,v,w)*Y[n]/abs(Y[n]);     
  mian:=mian+sqr(Lip(i,v,w))/abs(Y[n]);
     Result:=licz/mian;
 end;
end;

function TForm4.f2(v:Real):Real;
var i:integer;
begin
 Result:=0;
 for i:=0 to n do
 begin
 Result:=Result+(Li(i,u,v,w)-Y[n])
 /abs(Y[n])*sqr(Li(i,u,v,w))*(X[n]-v);
 end;
end;

function TForm4.f3(w:Real):Real;
var i:integer;
begin
 Result:=0;
 for i:=0 to n do
begin
 Result:=Result+(Li(i,u,v,w)-Y[n])
 /abs(Y[n])*sqr(Li(i,u,v,w));
 end;
end;

function TForm4.funk2(v:Real):Real;
begin
  Result:=0;
  if row_stycz(funk3,f3,wStart,w)then  //wyznaczenie v -> x0(funk2,u)
  Result:=f2(v);
  wStart:=w;
end;

function TForm4.funk3(w:Real):Real;
begin
 u:=f1;
 Result:=f3(w);
 uStart:=u;
end;




procedure TForm4.Fit;
var
        i:integer; chi2,r1,r2:Real;
begin
  if row_stycz(funk2,f2,vStart,v)then
     //Rozwiązywanie równania Funk1[u,v(Funk2,u)]
  begin
   Edit1.text:=FloatToStr(u);
   Edit2.text:=FloatToStr(v);
   Edit3.text:=FloatToStr(w);
  //Series1.Clear;
  //Series2.Clear;
   chi2:=0;
   for i:=0 to n do
   begin
    r1:=Y[n]; r2:=(2*u/pi)*(w/(4*sqr(X[n]-v)+sqr(w)));
    Series1.AddXY(X[n],r1);
    Series2.AddXY(X[n],r2);


   chi2:=chi2+sqr(r2-r1)/abs(r1);

   end;
   chi2:=chi2/(n-3);
   Edit7.Text:=FloatToStr(chi2);
  end else ShowMessage('Brak rozwiązania');
end;


procedure TForm4.Button2Click(Sender: TObject);
begin
 vStart:=StrToFloat(Edit5.Text);
 wStart:=StrToFloat(Edit6.Text);
Fit;
end;

procedure TForm4.Button3Click(Sender: TObject);
begin
  Series1.Clear;
  Series2.Clear;
end;

end.

0

Skoro macie problem z ogarnięciem całości, to napiszę inaczej.

Jak wprowadzić dane pomiarowe z pliku tekstowego do tablicy (albo innego wynalazku) i żeby potem program brał każdą linijkę z wczytanego wcześniej pliku i obliczał?

Plik tekstowy ma budowę:
23 565
26 656
28 789
....

Do obliczeń potrzebuję wyciągnąć raz wszystkie liczby X - po kolei, a raz wszystkie liczby Y - po kolei.

A jakby jeszcze ktoś mi pomógł z wyświetleniem "przerobionych" X i Y na wykresie, to juz by było super.

Pozdrawiam.

0

Jeżeli nikt nie odpowiedział Tobie po dłuższym czasie to nie ogarnia tematu filtrowania tą metodą. Jak będziesz tak podbijał temat zamiast edytować to wyląduje on w Koszu. Co do obsługi pliku tekstowego to mogę podpowiedzieć, że jeżeli - jak widzę - piszesz w VCL to skorzystaj z klasy TStringList, a później pętla i konwersja typu string na liczbowe. Więcej informacji jest oczywiście dostępnych na mnóstwie stron do znalezienia w Google.

0
olesio napisał(a)

Co do obsługi pliku tekstowego to...

... skorzystaj z plików typowanych, nie będziesz musiał konwertować w kółko tych liczb i zbędnie kombinować; Zadeklaruj odpowiedni rekord i odczytuj liczby po ludzku;

1 użytkowników online, w tym zalogowanych: 0, gości: 1