diff --git a/Software/SensorCharacterisation/Makefile b/Software/SensorCharacterisation/Makefile new file mode 100755 index 0000000..a3b0a55 --- /dev/null +++ b/Software/SensorCharacterisation/Makefile @@ -0,0 +1,34 @@ +# +CC=$(CXX) +glib_cflags=$(shell pkg-config --cflags glib-2.0 gio-2.0) +glib_libs=$(shell pkg-config --libs glib-2.0 gio-2.0) + +ROOTC=$(shell root-config --cflags) +ROOTL=$(shell root-config --libs) +OPT=-g -fno-inline #-std=c++11 +CppFLAGS=$(OPT) -I. $(glib_cflags) +CXXFLAGS=-fPIC $(CppFLAGS) + + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + SO=so + SO_FLAGS=-shared + CXXFLAGS += -D LINUX +endif +ifeq ($(UNAME_S),Darwin) + SO=dylib + SO_FLAGS=-dynamiclib -undefined dynamic_lookup -install_name @rpath/$@ + CXXFLAGS += -D OSX +endif + +all: SensorCharacterisation + +SensorCharacterisation: SensorCharacterisation.C + c++ -I$(OPT) $(CXXFLAGS) $(ROOTC) -o $@ $^ $(LDLIBS) $(ROOTL) $(gliblibs) + + +clean: + rm -f *.o SensorCharacterisation + rm -rf *.dSYM + diff --git a/Software/SensorCharacterisation/SensorCharacterisation.C b/Software/SensorCharacterisation/SensorCharacterisation.C new file mode 100644 index 0000000..391572e --- /dev/null +++ b/Software/SensorCharacterisation/SensorCharacterisation.C @@ -0,0 +1,223 @@ +//************************************************ +// Author: Federica Lionetto +// Created on: 08/05/2015 +//************************************************ + +/* +SensorCharacterisation reads a text file (containing the bias voltage, the current, and the capacitance values measured with the probe station) and creates a ROOT file with the following information: +- current as a function of the bias voltage; +- inverse of the squared capacitance as a function of the bias voltage. + +Compile with: + +make + +Run with: + +./SensorCharacterisation [input text file] [additional folder] + +where + +- [input text file] is the complete path, including the folder and the filename, of the text file one wants to process; +- [additional folder] is the optional additional folder where the output will be saved. + +A folder named AnalysisResults will be created in a fixed location and a ROOT file will be saved in there. A folder named Figures will be created inside the folder named AnalysisResults, with some monitoring plots. + +If needed, an additional folder can be specified, that will be created inside the folder named AnalysisResults. +*/ + +#include "../Tools/Lib.C" +#include "../Tools/lhcbStyle.C" +#include "../Tools/Style.C" + +#include "../Tools/Par.C" + +void SensorCharacterisation(char *filename, char *externalPath=0); + +int main(int argc, char *argv[]) +{ + getLHCbStyle(); + PersonalStyle(); + + if ((argc ==2) && (string(argv[1]) == "--info")) + { + cout << "**************************************************" << endl; + + cout << "Some comments." << endl; + + cout << "**************************************************" << endl; + + return 0; + } + else if (argc < 2) + { + cout << "**************************************************" << endl; + + cout << "Error! Input file missing..." << endl; + cout << "Please use the following format:" << endl; + cout << "./SensorCharacterisation [1] [2]" << endl; + cout << "with:" << endl; + cout << "[1] = Input text file, complete path;" << endl; + cout << "[2] = Additional folder, optional." << endl; + cout << "Type ./SensorCharacterisation --info for more information." << endl; + + cout << "**************************************************" << endl; + + return 0; + } + else + { + cout << "File to process: " << argv[1] << endl; + if (argc == 2) + SensorCharacterisation(argv[1]); + else if (argc == 3) + SensorCharacterisation(argv[1],argv[2]); + else + { + cout << "Error! Too many arguments given..." << endl; + + return 0; + } + + return 0; + } +} + +void SensorCharacterisation(char *filename, char *externalPath) +{ + cout << "**************************************************" << endl; + cout << "Working on the ICV scan..." << endl; + cout << "**************************************************" << endl; + + // Do not comment this line. + gROOT->ProcessLine("#include "); + + int found; + + string filename_as_string = string(filename); + // Check that the filename provided corresponds to a text file. + found = filename_as_string.find(".dat"); + if (found==string::npos) { + cout << "Error! The filename provided is not associated to a text file." << endl; + return; + } + + // Open input text file. + ifstream datFile; + std::string line; + + // Number of rows to be read from the text files. + int rows; + + // Open file. + // Determine number of rows to be read from the text file. + datFile.open(filename_as_string.c_str()); + if (datFile.is_open()) { + rows = 0; + while (getline(datFile,line)) + rows++; + cout << "Number of rows in the input text file: " << rows << endl; + datFile.close(); + } + else + { + cout << "Unable to open file." << endl; + return; + } + + // Read the text file. + // Remember that the first row must be skipped. + float V; + float I; + float IErr; + float C; + float CErr; + + Int_t i; + + // Read text file. + vector vV; + vector vI; + vector vC; // 1/C^2. + vector vVErr; + vector vIErr; + vector vCErr; // Uncertainty on 1/C^2, according to sigma(1/C^2) = 2/C^3*sigma(C). + + // Save information. + datFile.open(filename_as_string.c_str()); + if (datFile.is_open()) { + i = 0; + while (getline(datFile,line)) { + if (i>0) { + // cout << line << endl; + istringstream iss(line); + iss >> V >> I >> IErr >> C >> CErr; + vV.push_back(V); + vI.push_back(I); + vC.push_back(1./(C*C)); + vVErr.push_back(0.); + vIErr.push_back(IErr); + vCErr.push_back((2.*CErr)/(C*C*C)); + } + i++; + } + datFile.close(); + } + else + { + cout << "Unable to open file." << endl; + return; + } + + float *aV = &vV[0]; + float *aI = &vI[0]; + float *aC = &vC[0]; + float *aVErr = &vVErr[0]; + float *aIErr = &vIErr[0]; + float *aCErr = &vCErr[0]; + + // Do some fanciness to get the directory right. + string analysis = "/disk/groups/hep/flionett/TestStand/AnalysisResults"; + if (externalPath!=0) + analysis = string(analysis+"/"+externalPath); + + string filename_as_string_no_path = filename_as_string.substr(filename_as_string.find_last_of('/')+1); + string filename_as_string_no_path_no_extension = filename_as_string_no_path.substr(0,filename_as_string_no_path.length()-4); + + // Create a folder named AnalysisResults. Do not worry, nothing bad is going to happen if the folder already exists. + string path_to_make = "mkdir -p "+analysis; + system(path_to_make.c_str()); + cout << "Setting output to: " << path_to_make << endl; + + // Create a folder named Figures inside the folder named AnalysisResults. + string path_to_make_figures = "mkdir "+analysis+"/Figures"; + system(path_to_make_figures.c_str()); + path_to_make_figures = "mkdir "+analysis+"/Figures"+"/SensorCharacterisation"; + system(path_to_make_figures.c_str()); + path_to_make_figures = "mkdir "+analysis+"/Figures"+"/SensorCharacterisation"+"/"+filename_as_string_no_path_no_extension; + system(path_to_make_figures.c_str()); + cout << "Setting figures to: " << path_to_make_figures << endl; + + TString path_to_figures = (string(path_to_make_figures)).substr((string(path_to_make_figures)).find_last_of(' ')+1); + + // Open output ROOT file. + TFile *output = TFile::Open(analysis+"/SensorCharacterisation-"+TString(filename_as_string_no_path_no_extension)+".root","RECREATE"); + + TCanvas *cIVScan = new TCanvas("cIVScan","",400,300); + TCanvas *cCVScan = new TCanvas("cCVScan","",400,300); + + int rowsData = rows-1; + + TGraphErrors *gIVScan = new TGraphErrors(rowsData,aV,aI,aVErr,aIErr); + TGraphErrors *gCVScan = new TGraphErrors(rowsData,aV,aC,aVErr,aCErr); + + InitGraphErrors(gIVScan,"IV scan","Bias voltage (V)","Current (#muA)"); + InitGraphErrors(gCVScan,"CV scan","Bias voltage (V)","Capacitance^{-2} (nF^{-2})"); + + DrawGraphErrors(cIVScan,gIVScan,"APE",path_to_figures); + DrawGraphErrors(cCVScan,gCVScan,"APE",path_to_figures); + + output->Close(); + + return; +}