#include #include #include #include #include #include "stim/envi/envi_header.h" #include "stim/envi/bip.h" #include "stim/envi/bil.h" #include "stim/envi/bsq.h" #include "stim/envi/envi.h" #include "stim/envi/binary.h" void progress_thread_double(double* e); extern stim::envi ENVI; extern unsigned char* MASK; /// Reads a file of numbers separated by lines and white space into a 2D STL array std::vector tokenize(std::string str){ // construct a stream from the string std::stringstream strstr(str); // use stream iterators to copy the stream to the vector as whitespace separated strings std::istream_iterator it(strstr); std::istream_iterator end; std::vector results(it, end); // send the vector to stdout. //std::ostream_iterator oit(std::cout); //std::copy(results.begin(), results.end(), oit); return results; } /// Convert a metric file into an array of metric parameters std::vector< std::vector > read_metric_list(std::string filename){ std::ifstream infile(filename); if(!infile){ std::cout<<"ERROR opening metric file: "< > metrics; std::string line; //stores the metric parameters as a series of values in text while(std::getline(infile, line)){ //for each line in the input file std::vector tokens = tokenize(line); //break the line into tokens std::vector metric_params; //create an array to store the metric parameters for(size_t t = 0; t < tokens.size(); t++){ //for each token metric_params.push_back(atof(tokens[t].c_str())); } metrics.push_back(metric_params); } return metrics; //return the list of metrics and parameters } /// Creates an ENVI file filled with the given metrics, based on the Bhargava format void create_metric_file(std::vector< std::vector > metrics, std::string outfile){ //warn if the data set is BIP or BIL if (ENVI.header.interleave == stim::envi_header::BIL || ENVI.header.interleave == stim::envi_header::BIP) { std::cout << "WARNING: metric processing is slow for BIL and BIP files - recommend changing to BSQ" << std::endl; } double progress = 0; std::thread t1(progress_thread_double, &progress); //start the progress bar thread std::ofstream target(outfile.c_str(), std::ios::binary); //create an output file for writing the metrics size_t XYbytes = ENVI.header.samples * ENVI.header.lines * ENVI.header.valsize(); //size of a band in bytes void* M = malloc(XYbytes); //allocate space to store the metric result stim::envi_header new_header = ENVI.header; //copy the current header new_header.bands = metrics.size(); //set the number of bands to the number of metrics new_header.interleave = stim::envi_header::BSQ; //the metric output file will be BSQ new_header.band_names.resize(metrics.size()); //re-set the band names (names will be filled in below) new_header.wavelength.clear(); //clear the wavelengths - the output won't have wavelengths bool success = false; for(size_t m = 0; m < metrics.size(); m++){ //for each metric std::stringstream name_str; switch( (unsigned)metrics[m][0] ){ case 1: //peak height ratio if (ENVI.ph_to_ph(M, metrics[m][1], metrics[m][2], metrics[m][3], metrics[m][4], metrics[m][5], metrics[m][6], MASK)){ success = true; name_str << metrics[m][3] << " : " << metrics[m][6] << "\n"; new_header.band_names[m] = name_str.str(); } else success = false; break; case 2: //peak area to height ratio if (ENVI.pa_to_ph(M, metrics[m][1], metrics[m][2], metrics[m][3], metrics[m][4], metrics[m][5], metrics[m][6], metrics[m][7], MASK)) { success = true; name_str << metrics[m][3] << " : [" << metrics[m][6] << ", " << metrics[m][7] << "]\n"; new_header.band_names[m] = name_str.str(); } else success = false; break; case 3: //peak area to area ratio if (ENVI.pa_to_pa(M, metrics[m][1], metrics[m][2], metrics[m][3], metrics[m][4], metrics[m][5], metrics[m][6], metrics[m][7], metrics[m][8], MASK)) { success = true; name_str << "[" << metrics[m][3] << ", " << metrics[m][4] << "] : [" << metrics[m][6] << ", " << metrics[m][7] << "]\n"; new_header.band_names[m] = name_str.str(); } else success = false; break; case 4: //center of gravity if (ENVI.centroid(M, metrics[m][1], metrics[m][2], metrics[m][3], metrics[m][4], MASK)) { success = true; name_str << "[" << metrics[m][3] << ", " << metrics[m][4] << "]\n"; new_header.band_names[m] = name_str.str(); } else success = false; break; default: std::cout << "ERROR loading metric " << m << " from metric file" << std::endl; exit(1); } if (!success) { progress = 100; t1.join(); progress = ((double)(m + 1) / (double)metrics.size()) * 100; //save the progress std::cout << std::endl << "ERROR processing metric " << m + 1 << ":" << std::endl; std::cout << metrics[m][0] << " " << metrics[m][1] << " " << metrics[m][2] << " " << metrics[m][3] << " " << metrics[m][4] << " " << metrics[m][5] << " " << metrics[m][6] << " " << metrics[m][6] << " " << metrics[m][6] << std::endl; exit(1); } target.write((const char*)M, XYbytes); //write the metric results to a file progress = ( (double)(m+1) / (double)metrics.size() ) * 100; //save the progress } t1.join(); //end the progress bar thread new_header.save(outfile + ".hdr"); }