Search code examples
c++classroot-framework

Why does this code compile in ROOT, but does not do any of what it's meant to do?


I am trying to write a piece of code to perform the following tasks:

  1. Read in a data file consisting of average daily temperatures over several years (1722 to 2013)
  2. Find the yearly average temperatures
  3. Make a histogram of these yearly average temperatures
  4. Make a fit through this data such that, given a particular year (eg 2060), you can extrapolate to determine the average temperature for that year.

The code I've written so far, which I include below, should be able to perform tasks 1 to 3. It is divided into four parts: a header file "sketch.h", a C++ script "sketch.cpp", another C++ script "project.cpp" and some ROOT drawing file "rootlogon.C".

The files "sketch.h" and "sketch.cpp" contain the definition of a class and implementation of its members."project.cpp" is the file in which the analysis objects are instantiated. "rootlogon.C" has some predefined preferences for the appearance of the histograms and graphs.

The idea is that, if ROOT is run in the same folder as contains these 4 pieces of code, it will automatically load them all.

sketch.h

#ifndef TEMPTRENDER_H
#define TEMPTRENDER_H

#include <string>

class tempTrender 
{
public:
tempTrender(std::string filePath); //Construct using the specified filePath


//void tempPerYear(int yearToExtrapolate); //Make a histogram of average temperature per year, then fit and extrapolate to the given year

void read_datFile();  //will be used to read in the data file

private:
std::string pathToFile;   //my uppsala .dat file

int Year;
int Month;
int Day;
double Temp_exp;
double Temp_corr;
int dat_ID;

std::string helpString;
std::string filePath;

int numEntries; //total number of measurements done (entries in the data set)

int totTemp; //sum of daily temperatures in a given year
int counter;
int first_Year; //the year in which the measurements began
double AvgTemp; //average annual temperature

};

#endif

sketch.cpp

#include <iostream>
#include "sketch.h"
#include <fstream>
#include <string>
#include <sstream>

//ROOT library objects
#include <TF1.h> // 1d function class
#include <TH1.h> // 1d histogram classes
#include <TH2.h> // 2d histogram classes
#include <TRandom.h> // random generators
#include <TStyle.h>  // style object
#include <TMath.h>   // math functions
#include <TCanvas.h> // canvas object
#include <TGraph.h>  //For the graphs part
#include <TLegend.h>  //for the legends

using namespace std;


tempTrender::tempTrender(string filePath)
{
std::cout << "The user supplied " << filePath << " as the path to the data file." << endl;
string pathToFile = filePath;
}

//reading in data file
void tempTrender::read_datFile()
{
ifstream datFile(filePath.c_str());   //opening data file, as a C-string for later manipulation

if(!datFile) cout<<"Error: the file could not be read"<<endl; //just checking if the file was read in successfully ;-)

int n = 0; //initialise a counter
while(getline(datFile, helpString)) n++; //counting the number of lines in the data set;
numEntries = n;

//returning to the beginning of .dat file
datFile.clear();
datFile.seekg(0, ios::beg);


for(int i=0; i<numEntries; i++)
{
datFile >> Year >> Month >> Day >> Temp_exp >> Temp_corr >> dat_ID; //putting input data into categories
    std::cout<<Year<<endl; //checking that the categories contain the right data
    std::cout<<"I'm alive"<<endl;
}

//calculating average temperature and creating a histogram of the values

TH1F* hAvgTemp = new TH1F("hAvgTemp", "Average Annual Temperature: 1722-2013" , 600, 1722, 2013);

    while(datFile>> Year >> Month >> Day >> Temp_exp >> Temp_corr >> dat_ID)
    {
        while(first_Year == 1722 && Year == first_Year)
        {
            for(int Month=0; Month < 13; Month++) //loop over every month
            {
                for(int Day =0; Day < 32; Day++) //loop over every day
                {
                    counter++; //count the number of measurements
                    totTemp += Temp_corr;  //sum up the daily temperatures over all months of first_Year
                    AvgTemp = (totTemp/counter); //average temperature for first_Year. One number.
                }
            }
            hAvgTemp->Fill(AvgTemp); //start filling a histogram with the average temperatures
            cout << AvgTemp << endl; //show that the calculation worked
        }
        first_Year = first_Year + 1; //go to the next year and run the loop again
    }

    //creating canvas for hAvgTemp histogram
    TCanvas* c2 = new TCanvas("c1", "hAvgTemp Canvas", 900, 600);
    hAvgTemp->SetMinimum(0);
    hAvgTemp->Draw();
    c2->SaveAs("AvgTemp.png");
   }

project.cpp

#include "sketch.h"
#include <string>
#include <iostream>

using namespace std;

void project()
{
string pathToFile = "path_to_datFile.dat"; //path to data file
tempTrender t(pathToFile); //Instantiate analysis object
//t.tempPerYear(2050);
}

rootlogon.C

void rootlogon() {
gStyle->SetOptStat(0); //Let's make our plots look a bit better. Get rid of the stat box
gStyle->SetOptTitle(0); //Get rid of the title (good plots use legends instead)
gStyle->SetTitleSize(0.05, "x"); //Use bigger text on the axes
gStyle->SetTitleSize(0.05, "y");
gStyle->SetLabelSize(0.05, "x"); //Use bigger labels too
gStyle->SetLabelSize(0.05, "y");
gStyle->SetPadTopMargin(0.05); //Change the margins to fit our new sizes
gStyle->SetPadRightMargin(0.05);
gStyle->SetPadBottomMargin(0.16);
gStyle->SetPadLeftMargin(0.16);

gROOT->ProcessLine(".L sketch.cpp+"); //Load the classes that we want to use automatically - Convenient!
gROOT->ProcessLine(".L project.cpp+"); //The + means to recompile only if it changed since last time
}

Data file extract

I have included below an extract from the data file I am analysing. The columns are: Year, Month, Day, Measured temperature, Corrected temperature and Data ID, respectively.

1722  1 12   1.9   1.8 1
1722  1 13   2.3   2.2 1
1722  1 14   1.8   1.7 1
1722  1 15    .9    .8 1
1722  1 16  -1.8  -1.9 1
.      .     .      .
2013 12 29   3.8   3.6 1
2013 12 30   1.6   1.4 1
2013 12 31   3.3   3.1 1

The code compiles in ROOT but does nothing else. I have tried for a long time, and without success, to figure out what is wrong with it. Any help would be highly appreciated. In addition, a hint towards how to approach task 4 would also be appreciated. I am rather new to C++, so criticism is welcome.


Solution

  • For the rootlogon.C script to actually do something you need to call a function. I believe you want to execute your "main" function named project(). If this is the case then you need to modify your rootlogon.C as such:

    void rootlogon() {
    
    // ...
    
    gROOT->ProcessLine(".L sketch.cpp+"); //Load the classes that we want to use automatically - Convenient!
    gROOT->ProcessLine(".L project.cpp+"); //The + means to recompile only if it changed since last time
    
    project(); // <- Add this line
    }
    

    The gROOT->ProcessLine(".L ...") directives just compile the code and load the libraries in ROOT but you still need to call the function.