Disturbance Storm Time Graph
I've created a program that read the DST files, makes a graph or a histogram based on users input of date/month and show max, min, mean and classification of the possible storm.
The Dst is a geomagnetic index which monitors the world wide magnetic storm level and, for this reason, it has long been used as an indirect measure of the ring current.
Dst index is actually a measurement of the longitudinally averaged ground perturbation at low-latitude magnetometer stations.
A magnetic storm consists of two or three phases: initial phase (not necessarily
in all storms), main phase and recovery phase, all identified from the time series of
the
Dst index (see Figure 1 and 2). The initial phase, which begins with
a storm sudden
commencement, is distinguished as a positive excursion in the ground magnetic field: As the CME (Coronal Mass ejection ) hits the magnetopause, the magnetopause is compressed, leading also to the increase of the ground field at the equator.
The storm main phase is characterized both by the rapid decrease of the Dst index as well as the equatorward motion of the auroral ovals and occurrence of auroral intensifications and substorms. After the main phase follows the recovery phase during which the Dst index slowly recovers to the level preceding the storm. During the recovery phase the auroral oval returns to its nominal
position and the overall magnetic activity subsides. [1]
From
my program you can graph an interval 08/15 08/20 in 2003 (the file
that is default), and you can see a class 4 geomagnetic storm :
Explanation of the program.
The program created is not an especially advanced program, an experienced programmer could probably make this program half the size.
I feel however that the program shows I have learned and mastered the use of classes, functions and pointers.
I have tried to make my main() as small and clean as possible by using classes and function.
I start by reading the dst file and inserting it into vectors using getline, afterwards I found that probably using ROOT's own class Ttree or Ntuple would be better, but still I feel this is good.
Afterwards a the main() calls the function meny which is a void, and prints the users choices.
A switch case part lets the user specify if he wants to use the predefined intervals ( month or whole year) or input own interval like 01/15 01/29 .
The former calls a function called lagdato( int ) which define the start and stop date of the interval, example if the users chooses «1» the lagdato will create a string valg = 01/01 01/30 January.
I then create a vector called y_axis (I generally try to avoid using arrays, but as you will see later the ROOT function requires a array so I need to convert it later, or make a pointer) and to integers with are defined using the finn() function.
The finn() function uses pointers. and will locate starting index in the array according to the users choice of interval and return that value.
Further the program calls the fillVector function which has the y_axis ,data_vector vector , starting index and end index as parameter. This function fills the vector y_axis with the values the user is interessted in.
Since I noticed you preferred histograms I also included a choice to draw one. However I really feel the DST index is more interesting watching using a graph.
The drawGraph() function, with vector, size_of_vector and string valg as parameters calls the ROOT classes for Graph or histogram and fills then with our newly created array.
Then I create an object of the class getValues which has to private variables, a vector and an integer, it uses a function called inn_values to fill these to variables and then each function in the class uses those values to find the highest value, lowest value and mean value, then a function showResult presents the results.
I've also included a lot of comments in the program.
Warning: wrong member access operator '.' dst.cc:152: Warning: wrong member access operator '.' dst.cc:153: Warning: wrong member access operator '.' dst.cc:160: Theese warnings comes from my conversion from vector to array
The program can be downloaded here:
and the default dst file for 2003:
The Dst files are available here: ftp://ftp.ngdc.noaa.gov/STP/GEOMAGNETIC_DATA/INDICES/DST/
Remember to change the char filnamn to the new dstname. Default is dst2003.
|
// // dstGraph // Paul Tenfjord // Studentnr: 185126 // Run application in ROOT: // // .L dst.cc // main(); // // #include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <iomanip> #include <cstdlib> using namespace std;
gROOT->Reset();
char filnamn[] = "dst2003";
class getValues { int t; vector<float> *kvector; public: void inn_values (vector<float>&, int); void showResult(); float mean (); float max (); float min (); };
void getValues::inn_values (vector<float>& vector_inn, int q) { kvector = &vector_inn; t = q; }
float getValues::mean () { float m_m =0; for(size_t i=0; i<t; ++i) { m_m += kvector->at(i); } return m_m/t; }
float getValues::max () { int maximumvalue = *max_element(kvector->begin(), kvector->end()); return maximumvalue; }
float getValues::min () { int minimumvalue = *min_element(kvector->begin(), kvector->end()); return minimumvalue;
} void getValues::showResult() { cout << "\n\nMean value: " << mean() << endl; cout << "Highest value: " << max() << endl; cout << "Lowest value: " << min() << endl; if(-50 < min() && -30 > min()) { cout << "\n Weak Storm -50 nT < Dst < -30 nT \n"; } if(-100 < min() && -50 > min()) { cout << "\n Moderate Storm -100 nT < Dst < -50 nT \n"; } if(-200 < min() && -100 > min()) { cout << "\n Intense Storm -200 nT < Dst < -100 nT \n"; } if(-200 > min()) { cout << "\nSuper Storm Dst < -200 nT \n"; } }
int finn(vector<string>& vector_inn, size_t f_q, string searchPar) // Using poiters, this function will locate starting index, with respect to date chosen, and return that value { float m_1=0; string temp_tal, temp_tal2; for(size_t f_i=0; f_i<f_q; ++f_i) { if((temp_tal = vector_inn[f_i].substr(5,2)) == searchPar.substr(0,2) && (temp_tal2 = vector_inn[f_i].substr(8,2)) == searchPar.substr(3,2)) // Extract month and date. { m_1 = f_i; } } return m_1; }
void fillVector(vector<float>& yaxis_inn, vector<string>& data_inn, int iSInn, int iEInn) {
float stringTOfloat; int chunkSize = 4; for (int i = iSInn; i <= iEInn; i++) { int strLength = data_inn[i].size(); for (int i_2 = chunkSize; i_2 < strLength - 4 ; i_2 += chunkSize) // Remove the first and last chunk. { stringstream s1s(data_inn[i].substr(i_2, chunkSize)); // Konvertere string til INT s1s >> stringTOfloat; // Convert string to float yaxis_inn.push_back(stringTOfloat); //Fill vector with values from the chosen range } }
}
void meny() { cout << "\nPlease which month you wish to see DST index for: \n" "01) January 02) February\n" "03) March 04) April\n" "05) May 06) June\n" "07) July 08) August\n" "09) September 10) October\n" "11) November 12) December\n" "13) Total (all year)\n" "14) Enter your own interval\n" "Type 0 to exit\n\n";
} string lagdato(int valg) { string valg_res; if(valg == 1) { valg_res = "01/01 01/31 January"; } if(valg == 2) { valg_res = "02/01 02/28 February"; } if(valg == 3) { valg_res = "03/01 03/31 March"; } if(valg == 4) { valg_res = "04/01 04/30 April"; } if(valg == 5) { valg_res = "05/01 05/31 May"; } if(valg == 6) { valg_res = "06/01 06/30 June"; } if(valg == 7) { valg_res = "07/01 07/31 July"; } if(valg == 8) { valg_res = "08/01 08/31 August"; } if(valg == 9) { valg_res = "09/01 09/30 September"; } if(valg == 10) { valg_res = "10/01 10/31 October"; } if(valg == 11) { valg_res = "11/01 11/30 November"; } if(valg == 12) { valg_res = "12/01 12/31 December"; } if(valg == 13) { valg_res = "01/01 12/31 One year"; } return valg_res; } void drawGraph(float *array_inn, int q, string valgInn) { float * xaxis_a = new float[q]; float klokke = 0.0417; //Just a way to define the x-axis so that each day is "1". for (int j=0; j < q ; j++) { xaxis_a[j] = j*klokke; }
// calling ROOT classes. TCanvas *c1 = new TCanvas("c1","DST INDEX",500,10,1700,500); c1->Clear(); c1.SetGridx(); c1.SetGridy(); c1->SetTitle("Disturbance Storm Time Graph"); TGraph *gr = new TGraph(q,xaxis_a,array_inn); gr->GetHistogram()->SetXTitle("Days"); const char * charTitle = valgInn.c_str(); //Passing a string to a function that needs const char* gr->SetTitle(charTitle); gr->GetHistogram()->SetYTitle("Dst [nT]"); gr.Draw("ALP"); // gr->Print(); }
void drawHistogram(float *array_inn, int q, string valgInn) { const char * charTitle = valgInn.c_str(); //Passing a string to a function that needs const char* TH1F *h1 = new TH1F("h1",charTitle, 500, -200, 70); TH1::AddDirectory(kFALSE); for (int i=0; i < q; i++) { h1.Fill(array_inn[i]);
}
h1.Draw();
}
int main() {
string t; vector<string> DATA_vector; vector<string> dato_vector; ifstream myfile; myfile.open(filnamn);
if(!myfile) { // file couldn't be opened cerr << "Error: file could not be opened" << endl; exit(1); }
while(getline(myfile, t)) // while(getline(myfile, t, '\n')), notat: If a character delimiter //is specified, then getline() will use delimiter to decide when to stop reading data. { if (t.find('DST') != string::npos) // If the string does not contain DST string, // the result of the find method will be the value string::npos. { dato_vector.push_back(t.substr(0,10)); DATA_vector.push_back(t.substr(16)); }
} /* When taking a datafile directly from DST FTP, the last line of the file contains a special caracter which will cause the program to call substr with a parameter that is out of range. This is how I think it's causing problems: Example: string test = "test"; test.substr(0,6); will cause : terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::substr Aborted The find('DST') will search each line, if it contains this string it will give you the position, and the if setence will cause the while loop to only add lines containing to the vectors. This is a workaround so that the user don't have to edit the downloaded DST file. Another possibility would be to rewrite the file, but I found that rather as a rather drastic method. My method does however give me an compiler warning: dst.cpp:38: warning: overflow in implicit constant conversion I think that this is the kind of warning you get when you for example try to convert a float to an int. I'm not sure how to fix this. */
//This gives me some warnings, however according to cplusplus.com, this // is the correct way to do it. I tried to use "copy(v.begin()....)" // which gave me even more warnings. //TGraph only supports array, hence this conversion from vectors to array
meny(); // Will execute the meny function. string valg; int number; cin >> number; switch (number) { case 0: exit(1); case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: valg = lagdato(number); break; case 14: cout << "Example : 08/15 08/20\n \n"; char name[256]; cin.ignore(); cout << "Enter interval : "; //I had some problems using getline(string) //I found no other solution than reading //inn-data as char and convert to string cin.getline (name,256); valg = name; break; default: cout << "Not a choice, choosing default value '1'\n"; valg = lagdato(1); break; }
// Will use this vector to represent the final values after vector<float> y_axis; // user has chosen which month or which interval he wish to see. int iS = finn(dato_vector,dato_vector.size(),valg); int iE = finn(dato_vector,dato_vector.size(),valg.substr(6,5));
fillVector(y_axis, DATA_vector , iS, iE);
cout << "Plot data in 1) Graph (Recommanded), 2) Histogram \n \n" << "Choose 1 or 2 : "; int graphChoice; cin >> graphChoice; //&y_axis[0] gives me some warnings, however accorinding to cplusplus.com, this // is the correct way to convert a vector to an array. I tried to use "copy(v.begin()....)" // which gave me even more warnings. //TGraph only supports array, hence this conversion from vectors to array if(graphChoice == 1) { drawGraph(&y_axis[0], y_axis.size(), valg); } else if(graphChoice == 2) { drawHistogram(&y_axis[0], y_axis.size(), valg); } else { cout<<"Error: Invalid number\n" << exit(1) << endl << endl;}
getValues stormValues; stormValues.inn_values(y_axis, y_axis.size()); cout << stormValues.showResult() << endl;
/*cout << "Position in vector start " << finn(dato_vector,dato_vector.size(),valg) << endl; cout << "Position in vector stop " << finn(dato_vector,dato_vector.size(),valg.substr(6,5)) << endl;*/
return 0; } |
I am available by email paul.tenfjord@student.uib.no in the next few days. After that I am on vacation but will probably not check my email daily.
[1] theory.physics.helsinki.fi/~plasma/lect09/Dynamics_text.pdf
Paul Tenfjord
Studentnr: 185126