Blame view

src/proc/spero.cpp 5.84 KB
5f3cba02   David Mayerich   initial public co...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  #include "stim/parser/filename.h"
  #include "stim/envi/envi.h"
  #include "stim/visualization/colormap.h"
  
  #include <thread>
  #include <algorithm>
  #include <unordered_map>
  #include <fstream>
  void progress_thread_double(double* e);		//progress bar threaded function
  
  struct speroFile{
  	int x;
  	int y;
  	stim::filename headername;
  };
  
  void spero_coord(int &x, int &y, stim::filename filename){
  
  	//get the file prefix
  	std::string prefix = filename.get_prefix();
  
  	//these files are in the format:
  	//		???????????[xxxxx_yyyyy][??????????].hdr
  
  	//first find the x coordinate
  
  	//find the position of the first bracket
  	size_t start = prefix.find_first_of("[") + 1;				//find the first element of the y coordinate
  	prefix = prefix.substr(start, prefix.length() - start);
  	size_t end = prefix.find_first_of("_");					//find the index of the last element of the y coordinate
  
  	std::string x_string = prefix.substr(0, end);
  
  	x = atoi(x_string.c_str());
  
  	//crop out the x coordinate and the last underscore
  	prefix = prefix.substr(end + 1, prefix.length() - end);
  	end = prefix.find_first_of("]");
  	std::string y_string = prefix.substr(0, end);
  
  	y = atoi(y_string.c_str());
  	//find the y coordinate using the same method as above
  /*	size_t x_start = prefix.find_last_of("_");
  	std::string x_string = prefix.substr(x_start + 1);
  	x = atoi(x_string.c_str());*/
  }
  
  void mosaic_spero(std::string directory, std::string outfile){
  
  	std::cout<<"Building a mosaic from SPERO frames..."<<std::endl;
  
  	//generate a list of dmd files
  	stim::filename f = directory + "/*.hdr";
  	std::vector<stim::filename> hdr_list = f.get_list();
  
  	std::vector<speroFile> speroFiles;											//create a list of spero files
  	speroFiles.resize(hdr_list.size());											//pre-allocate to save time (we know how many there are)
  	for(size_t i = 0; i < hdr_list.size(); i++){								//for each header name
  		spero_coord(speroFiles[i].x, speroFiles[i].y, hdr_list[i]);
  		speroFiles[i].headername = hdr_list[i].str();
  		//speroFiles[i].file.open(hdr_list[i].str_noext(), hdr_list[i].str());
  		//speroFiles[i].file.close();												//close the file (can only keep so many open at once)
  	}
  
  	//calculate the height of the image by looking at how many files have the same x coordinate
  	size_t height = 0;									//stores the width of the array
  	int first_x;										//the first x value encountered
  	for(size_t i = 0; i < speroFiles.size(); i++){		//for each file
  		if(i == 0) first_x = speroFiles[i].x;			//if this is the first file, store the x coordinate
  		else{											//otherwise
  			if(speroFiles[i].x != first_x){				//if the x-coord of this file is not the same as the first file
  				height = (int)i;							//we now know the number of files
  				break;									//exit the loop
  			}
  		}
  	}
  	size_t width = speroFiles.size() / height;			//the number of files should be divisible by the width to get the height
  
  	
  	std::vector<int> yvals(height);						//stores the height values
  	for(size_t i = 0; i < height; i++)					//go through the first "width" files and store their y values
  		yvals[i] = speroFiles[i].y;
  
  	std::vector<int> xvals(width);							//stores the width values
  	for(size_t i = 0; i < speroFiles.size(); i += height)	//go through every "width" file and store the x coordinate
  		xvals[i/height] = speroFiles[i].x;
  
  	std::sort(&yvals[0], &yvals[0] + yvals.size());			//sort both arrays of coordinates
  	std::sort(&xvals[0], &xvals[0] + xvals.size());
  	
  	//create a mapping from the x and y coordinates to their indices
  	std::unordered_map<int, size_t> x2idx;					
  	std::unordered_map<int, size_t> y2idx;
  
  	for(size_t i = 0; i < height; i++) y2idx.insert(std::pair<int, size_t>(yvals[i], i));	//unordered maps now give an index for a coordinate
  	for(size_t i = 0; i < width; i++)  x2idx.insert(std::pair<int, size_t>(xvals[i], i));
  
  	std::vector<stim::envi> M;							//create an array of ENVI files in mosaic order
  	M.resize(speroFiles.size());
  
  	size_t xi, yi;
  	for(size_t i = 0; i < M.size(); i++){				//for each input file
  		xi = x2idx[speroFiles[i].x];					//get the x and y indices for this file's position in the mosaic
  		yi = y2idx[speroFiles[i].y];
  
  		M[yi * width + xi].open(speroFiles[i].headername.str_noext(), speroFiles[i].headername.str());	//open the ENVI file and set parameters
  		M[yi * width + xi].close();						//close the file, since we can only open so many
  	}
  
  	std::ofstream target(outfile.c_str(), std::ios::binary);	//create a file to store the output
  
  	stim::envi_header h = M[0].header;			//create a header for the mosaic
  	h.samples *= width;
  	h.lines *= height;
  	size_t tile_width = M[0].header.samples;
  	size_t tile_height = M[0].header.lines;
  
  	//h.bands = 10;
  
  	double progress = 0;
  	std::thread t1(progress_thread_double, &progress);		//start the progress bar thread
  
  	float* band = (float*) malloc(h.samples * h.lines * sizeof(float));	//allocate space for a band image
  	float* tile_band = (float*) malloc(tile_width * tile_height * sizeof(float));
  	size_t dst, src;
  	for(size_t b = 0; b < h.bands; b++){
  		for(size_t yi = 0; yi < height; yi++){
  			for(size_t xi = 0; xi < width; xi++){
  				M[yi * width + xi].open();
  				M[yi * width + xi].band_index(tile_band, b);
  				for(size_t y = 0; y < tile_height; y++){
  					dst = (yi * tile_height + tile_height - y - 1) * h.samples + xi * tile_width;
  					src = y * tile_width;
  					memcpy(band + dst, tile_band + src, sizeof(float) * tile_width);
  				}
  				//stim::cpu2image(tile_band, outfile + ".bmp", tile_width, tile_height, stim::cmBrewer);
  				//exit(1);
  				M[yi * width + xi].close();
  
  				progress = (double)((b+1) * (yi+1) * (xi + 1)) / (width * height * h.bands) * 100;
  			}
  		}
  		target.write((char*)band, h.samples * h.lines * sizeof(float));
  		//stim::cpu2image(band, outfile + ".bmp", h.samples, h.lines, stim::cmBrewer);
  		//exit(1);
  	}
  
  	t1.join();								//wait for the thread to terminate
  
  	target.close();							//close the output file
  	h.save(outfile + ".hdr");				//write the header
  
  	free(band);
  }