//+********************************************************************** // // File: spec_retriever.cpp // // Project: Fable data to NeXus translation // // Description: code for implementing a retriever of data from spec files. // It is added into NXtranslate program in the form of plugin. // By parsing a XML configuration file of // NXtranslate program using this plugin, data from SPEC tags // can be read and stored in NeXus file. // // Author(s): Jaroslaw Butanowicz // // Original: March 2006 // //+********************************************************************** #include #include #include #include #include #include #include "spec_retriever.h" #include "SPEClib.h" #include "../node.h" #include "../node_util.h" #include "../string_util.h" #include "../tree.hh" // //delimiter used to separate statements in location parameter. //used in command parser // #define DELIMITER ':' using std::ifstream; using std::invalid_argument; using std::runtime_error; using std::string; using std::cout; using std::endl; using std::vector; /** * Function parses location command from .xml configuration file. * It divides command on three parts. letter:label:scan_number. * It do all the checkins for correctness of the command. Command need * to be built from these three parts(letter, label, int) separated by colons ':'. * Parameters: input - string location(command) * output - char letter, char *label, int scan number * Returns: true if letter indicates that label is needed(L, O, U), * false for the case of letters(D, F, C) were label can be ommited. * In case of any other labels error will occur. */ bool command_parser(const string &location, char &letter, char *label, int &scan){ bool if_label=0; int size = location.size(); int counter=0; int second_delimiter; // //location cannot be empty // if(size<=0) throw invalid_argument(" cannot parse empty string "); // //check second place in string for delimiter(L:label:scna_number) // if(location[1]!=DELIMITER) throw invalid_argument(" after the letter suppose to be delimiter "); // //count delimiters in location, starting from first one // for(int i=2; i &tr){ char letter; char label[BUFFER_SIZE]; int scan_number; // //parse location, and check for case with label // if(command_parser(location, letter, label, scan_number)){ // //case for L tag // if(letter=='L'){ // //iterators for setting the structure of the tree of NeXus file // tree::iterator root, first_gen, second_gen; // //case for every labels from the scan // if(!strcmp(label,"*")){ string scan_group = "scan_";//template for name of the scan NXentry char lab[BUFFER_SIZE];//name of the label char number[5];//temporary array for storing scan number int MaxLabel; // //case for every scans(L:*:*) // if(scan_number==0){ auto_translation(tr); } // //case for L:*:scan_number, store data of every labels for given scan // else{ // //create folder for the interesting scan // Node node("empty", "NXentry"); first_gen = tr.insert(tr.end(),node); // //go to the scan and count number of measurements // scan_rewinder(infile, scan_number); const int size_of_data = count_data_sets(infile); if(!(size_of_data)){ cout<<" No data was collected in the scan "< data(size_of_data); const int dims[1]={size_of_data}; // //count labels // scan_rewinder(infile,scan_number); if(!(MaxLabel = count_columns(infile))){ cout<<" No labels in the scan "< data(size_of_data); const int dims[1]={size_of_data}; // //store values read from scan // get_values(infile, label_position, &(data[0]), scan_number); // //insert data item with label values // Node node(location, (void*)&(data[0]), 1, dims, NX_FLOAT64); tr.insert(tr.begin(),node); } // //case for single label from every scans(L:label:*) // else{ // //prepare name for scan entry // string scan_group = "scan_"; char number[5]; string item_name = string(label); // //insert "_" instead of every spaces in label name to name data item in nexus // for(int a=0; a data(size_of_data); const int dims[1]={size_of_data}; // //fetch data corresponding to label in i-th scan // get_values(infile, label_position, &(data[0]), i); // //insert data group with the name of the scan, // Node child_group(scan_group, "NXdata"); second_gen = tr.append_child(first_gen, child_group); // //store plottable data item in the group NXdata, for given scan // Node node_child(item_name, (void*)&(data[0]), 1, dims, NX_FLOAT64); tr.append_child(second_gen,node_child); } } } } // //case for motors // else if(letter=='O'){ // //iterators for setting the structure of the tree of NeXus file // tree::iterator root, first_gen, second_gen; int motor_position; int motor_group; int motor_groups; int motors_in_last_group; double motor_value[1];//single values for motors const int dims[1]={1}; // //case for every motors from the scan // if(!strcmp(label,"*")){ string scan_group = "moto_"; char number[5]; char lab[BUFFER_SIZE];//name of the label // //create folder for the interesting scan // Node node("empty", "NXlog"); first_gen = tr.insert(tr.end(),node); scan_rewinder(infile, scan_number); // //count motor groups // if(!(motor_groups = motor_counter(infile))){ cout<<"NO motors in the file\n"; exit(1); } // //count motors in last group, in the rest of the groups there is always 8 // scan_rewinder(infile, scan_number); if(!(motors_in_last_group = m_label_counter(infile, motor_groups-1 ))) { cout<<"NO motors in last group\n"; exit(1); } // //loop through motors from every groups apart of the last one // for(int j=0; j(strlen(refill))}; // //store refill mode item in the place in hierarchy from where it was invoked // Node node(location, (void*)refill, 1, dims, NX_CHAR); tr.insert(tr.begin(),node); } // //case for time of refill // else if(!(strcmp(label, "time"))){ // //go to scan // scan_rewinder(infile, scan_number); // //read time of refill, print error if it is not found // if(!(refill_time(infile, refill))){ cout<<" There is no refill time indicated in scan "<(strlen(refill))}; // //store refill time in the place from invoked // Node node(location, (void*)refill, 1, dims, NX_CHAR); tr.insert(tr.begin(),node); } else { // //letter does not match anything in SPEC file // cout<<" Wrong label "<::iterator root; // //prepare name for scan date // string scan_group = "date_of_scan_"; char number[5]; // //create entry for data corresponding to dates of every scans // Node node("empty", "NXlog"); root = tr.insert(tr.end(),node); // //count scans // int scan_total=total_scans(infile); // //fetch data from every scans // for(int i=1; i(strlen(result))}; // //store just read data in the place from invoked // Node node_child(scan_group, (void*)result, 1, dims, NX_CHAR); tr.append_child(root,node_child); } } break; default: break; //it will never go here } if(scan_number!=0){ const int dims[1]={static_cast(strlen(result))}; // //store just read data in the place from invoked // Node node(location, (void*)result, 1, dims, NX_CHAR); tr.insert(tr.begin(),node); } } } // //indicate mime type // const string SpecRetriever::MIME_TYPE("spec"); string SpecRetriever::toString() const{ return "["+MIME_TYPE+"] "+source; } /** * Method is used for automatic translation of the file. * Details about the rules of translation are in the documantation of the retriever. * The method is called from the SpecRetriever::getDate() method, when * location paramter is "L:*:*". The whole Spec file is translated automatically. */ void SpecRetriever::auto_translation(tree &t){ string scan_group = "scan_";//template for name of the scan NXentry char lab[BUFFER_SIZE];//name of the label char number[5];//temporary array for storing scan number int MaxLabel; int size_of_data; tree::iterator root, first_gen, second_gen; // //set number of scans from the file // int MAX =total_scans(infile); // //for text fields of date, userId, file name // char result[BUFFER_SIZE]; // //create root folder, it is advised to call for L:*:* from root level // Node node("empty", "NXroot"); root = t.insert(t.end(),node);//insert root to the tree Node node_user("User_data", "NXuser"); first_gen = t.append_child(root,node_user); // //read file name of SPEC file // if(!get_file_name(infile, result)){ cout<<" File name not specified. Empty string written into the nexus file.\n"; strcpy(result," "); } // //dimensions of file name // const int dims_file[1]={static_cast(strlen(result))}; // //store file name in the user group // Node node_file("file_name", (void*)result, 1, dims_file, NX_CHAR); t.append_child(first_gen,node_file); // //read user ID // if(!get_userID(infile, result)){ cout<<" User Id not specified. Empty string written into the nexus file.\n"; strcpy(result," "); } // //dimensions of userId // const int dims_id[1]={static_cast(strlen(result))}; // //store user Id in the user group // Node node_id("user_id", (void*)result, 1, dims_id, NX_CHAR); t.append_child(first_gen,node_id); // //go thru every scans // for(int i=1; i data(size_of_data); const int dims[1]={size_of_data}; // //go back to scan and count every labels // scan_rewinder(infile,i); if(!(MaxLabel = count_columns(infile))){ cout<<" No labels in the scan "<(strlen(result))}; // //go to the scan // scan_rewinder(infile, i); // //store data in NXlog group // Node node_date("date_of_scan", (void*)result, 1, dims_date, NX_CHAR); t.append_child(second_gen,node_date); } }