Úvod do praktické fyziky NOFY055

Programování pro statistiku a zpracování měření v příkladech

Mgr. Jan Matoušek, Ph.D.
Výběr jazyka/prostředí: python  root  
Zpět na hlavní stránku

Hello world program

Co je potřeba udělat, abych dostal nejjednoduší možný funkční program?
Vytvořím soubor test.cc, obsahující:
void test()
{
  printf("Hello world!\n"); // \n je odřádkování
}
Program spustím z příkazového řádku:
user@machine:~$ root test.cc
root [0] Hello world!
Prostředí ROOTu opustím příkazem
root [1] .q

Proměnné, podmínka

Definice proměnných, jednoduchá operace, vypsání výsledku:
void variables()
{
  int n = 2;      // integer (celé číslo)
  double x = 3.5;    // číslo 's plovoucí desetinnou čárkou'
  printf("n = %i, x = %f\n", n, x);  // %i je nahrazeno integrem, %f doublem
  double y = n * x + 4;
  if (y >= 0)  // podmínka: jestliže y je kladné
  {
    double z = sqrt(y);
    printf("y = %f, z = sqrt(y) = %f\n", y, z);
  }
  else  // je-li y záporné
    printf("y = %f, z = sqrt(y) není definováno.\n",y);
  // je-li v podmínce jen 1 řádek, nemusí se psát složené závorky
}

Generování náhodných čísel

Generujeme 100 čísel s rovnoměrným rozdělením v intervalu (0,1):
void rndm()
{
  TRandom3* random = new TRandom3();  // nebo např. TRandom3(1234), kde 1234 je semínko

  for (int i = 0; i < 100; i++)  // pro všechna i = 0, 1,..., 99 udělej:
  {
    double x = random->Rndm();
    printf("%f\n",x);
  }
}
Lze udělat i jiná rozdělení, viz https://root.cern.ch/doc/master/classTRandom.html
Generování čísel do pole:
void rndm_array()
{
  const int N = 100;  // musí být const, aby mohl být délkou pole (pole na zásobníku)
  double x[N];
  TRandom3* random = new TRandom3();

  for (int i = 0; i < N; i++)
    x[i] = random->Rndm();  // je-li v cyklu 1 příkaz, nemusí se psát složené závorky

  // vypsání pole:
  for (int i = 0; i < N; i++)
    printf("%i\t%f\n", i, x[i]);
}

Graf

Jednoduchý graf funkce sin(2x):
void graph()
{
  int N = 100;  // počet bodů
  double xMin = -TMath::Pi();
  double xMax = TMath::Pi();
  double dx = (xMax - xMin) / N;

  TGraph* graph = new TGraph(N);  // konstruktor bodového grafu s N body
  for (int i = 0; i < N; i++)
  {
    double x = xMin + i * dx;
    graph->SetPoint(i, x, sin(2*x));
  }

  graph->SetTitle("");  // jinak má nadpis "Graph"
  graph->GetXaxis()->SetTitle("x");
  graph->GetYaxis()->SetTitle("y");
  graph->SetMarkerStyle(2);  // vybere symbol bodu
  graph->Draw("PA");  // PA vykreslí graf jako bodový a s osami (jinak se vykreslí čárou)

  // ROOT taky zná objekt 'funkce':
  TF1* func = new TF1("func","cos(2*x)",xMin,xMax);
  func->Draw("SAME");  // SAME vykreslí funkci přes existující graf (jinak by se smazal)
}
Přehled toho, jak se dá graf upravit je např. tady https://root.cern.ch/doc/master/classTGraphPainter.htmlUkázka grafu

Histogram

Histogram reprezentuje distribuci nějaké numerické veličiny. Je to typ grafu, kde vertikální osa vyjadřuje četnost výskytu sledované veličiny v intervalech (binech) znázorněných na horizontální ose. Histogram uděláme následovně: Nejdřív rozdělíme rozsah dané veličiny na biny. Potom sledujeme danou veličinu v nějakém počtu případů a zaznamenáme, kolikrát leží ve kterém binu. Příklad vytvoření histogramu a jeho naplnění exponenciálně rozdělenou náhodnou veličinou:
void histo()
{
  int N = 100;
  double tau = 1;
  TRandom3* random = new TRandom3();

  int nBins = 10;
  double xmin = 0;
  double xmax = -1;  // nebo např. 5*tau
  TH1D* hist = new TH1D("hist", "", nBins, xmin, xmax);
  // konstruktor 1-dimenzionálního histogramu (jmeno, titulek, počet binů, xmin, xmax)
  // je-li xmax < xmin, zvolí se automaticky
  hist->GetXaxis()->SetTitle("x");

  for (int i = 0; i < N; i++)
    hist->Fill(random->Exp(tau));  // vložit jedno náhodné číslo do histogramu

  hist->Draw();

  // přístup k hranicím a obsahu binů:
  printf("underflow: %f, overflow: %f\n",
    hist->GetBinContent(0),  // nultý bin = počet čísel pod rozsahem histogramu
    hist->GetBinContent(nBins+1));  // nBins+1. bin: počet čísel nad rozsahem
  for (int i = 1; i <= nBins; i++)
    printf("bin [%f, %f], případů: %f\n", hist->GetBinLowEdge(i),
      hist->GetBinContent(i), hist->GetBinLowEdge(i+1));
}
Ukázka histogramuVolby zobrazení histogramu: https://root.cern.ch/doc/master/classTHistPainter.html

Zápis do souboru

Zapíšeme do souboru dvojice náhodných čísel:
void out()
{
  FILE* file = fopen("data.txt","w");
  TRandom3* random = new TRandom3();

  for (int i = 0; i < 10; i++)
  {
    double x = random->Gaus(0,0.5);  // normální rozdělení, mu = 0, sigma = 0.5
    double y = random->Gaus(2.5,1);  // mu = 2.5, sigma = 1
    fprintf(file,"%f\t%f\n", x, y);
  }
  fclose(file);
}

Čtení ze souboru

Následující program přečte textový soubor vytvořený v předchozím příkladě a spočítá průměr každého sloupce (odhad střední hodnoty rozdělení).
void in()
{
  FILE* file = fopen("data.txt","r");
  double mx = 0;
  double my = 0;
  double x, y;
  int n = 0;

  while(fscanf(file,"%lf%lf", &x, &y) == 2)  // cykluj, dokud přečteš 2 čísla
  {
    printf("přečteno: %f\t%f\n", x, y);
    mx += x;  // přičti x k mx
    my += y;
    n++;
  }
  fclose(file);
  mx /= n;  // x = x / n
  my /= n;
  printf("---------------------------------\n");
  printf("průměrné x = %f, průměrné y = %f\n", mx, my);
}

Výběr jazyka/prostředí: python  root  
Zpět na hlavní stránku