Commit f4069d3f54b21a7ee54160b0f839fd3a4b767dfe

Authored by David Mayerich
1 parent 95f1e985

fixed the crop function to work with wavelength

Showing 3 changed files with 158 additions and 53 deletions   Show diff stats
@@ -1368,6 +1368,39 @@ public: @@ -1368,6 +1368,39 @@ public:
1368 return false; 1368 return false;
1369 } 1369 }
1370 1370
  1371 + void band_bounds(double wavelength, size_t& low, size_t& high) {
  1372 + if (header.interleave == envi_header::BSQ) { //if the infile is bsq file
  1373 + if (header.data_type == envi_header::float32)
  1374 + ((bsq<float>*)file)->band_bounds(wavelength, low, high);
  1375 + else if (header.data_type == envi_header::float64)
  1376 + ((bsq<double>*)file)->band_bounds(wavelength, low, high);
  1377 + else {
  1378 + std::cout << "ERROR: unidentified data type" << std::endl;
  1379 + exit(1);
  1380 + }
  1381 + }
  1382 + else if (header.interleave == envi_header::BIL) {
  1383 + if (header.data_type == envi_header::float32)
  1384 + ((bil<float>*)file)->band_bounds(wavelength, low, high);
  1385 + else if (header.data_type == envi_header::float64)
  1386 + ((bil<double>*)file)->band_bounds(wavelength, low, high);
  1387 + else {
  1388 + std::cout << "ERROR: unidentified data type" << std::endl;
  1389 + exit(1);
  1390 + }
  1391 + }
  1392 + else if (header.interleave == envi_header::BIP) {
  1393 + if (header.data_type == envi_header::float32)
  1394 + ((bip<float>*)file)->band_bounds(wavelength, low, high);
  1395 + else if (header.data_type == envi_header::float64)
  1396 + ((bip<double>*)file)->band_bounds(wavelength, low, high);
  1397 + else {
  1398 + std::cout << "ERROR: unidentified data type" << std::endl;
  1399 + exit(1);
  1400 + }
  1401 + }
  1402 + }
  1403 +
1371 // Retrieve a spectrum at the specified 1D location 1404 // Retrieve a spectrum at the specified 1D location
1372 1405
1373 /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) 1406 /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T)
@@ -62,31 +62,6 @@ protected: @@ -62,31 +62,6 @@ protected:
62 return (T)((1.0 - alpha) * low_v + alpha * high_v); //interpolate 62 return (T)((1.0 - alpha) * low_v + alpha * high_v); //interpolate
63 } 63 }
64 64
65 - /// Gets the two band indices surrounding a given wavelength  
66 - void band_bounds(double wavelength, size_t& low, size_t& high){  
67 - size_t B = Z();  
68 - for(high = 0; high < B; high++){  
69 - if(w[high] > wavelength) break;  
70 - }  
71 - low = 0;  
72 - if(high > 0)  
73 - low = high-1;  
74 - }  
75 -  
76 - /// Get the list of band numbers that bound a list of wavelengths  
77 - void band_bounds(std::vector<double> wavelengths,  
78 - std::vector<unsigned long long>& low_bands,  
79 - std::vector<unsigned long long>& high_bands){  
80 -  
81 - unsigned long long W = w.size(); //get the number of wavelengths in the list  
82 - low_bands.resize(W); //pre-allocate space for the band lists  
83 - high_bands.resize(W);  
84 -  
85 - for(unsigned long long wl = 0; wl < W; wl++){ //for each wavelength  
86 - band_bounds(wavelengths[wl], low_bands[wl], high_bands[wl]); //find the low and high bands  
87 - }  
88 - }  
89 -  
90 /// Returns the interpolated in the given spectrum based on the given wavelength 65 /// Returns the interpolated in the given spectrum based on the given wavelength
91 66
92 /// @param s is the spectrum in main memory of length Z() 67 /// @param s is the spectrum in main memory of length Z()
@@ -139,6 +114,31 @@ protected: @@ -139,6 +114,31 @@ protected:
139 } 114 }
140 115
141 public: 116 public:
  117 +
  118 + /// Gets the two band indices surrounding a given wavelength
  119 + void band_bounds(double wavelength, size_t& low, size_t& high) {
  120 + size_t B = Z();
  121 + for (high = 0; high < B; high++) {
  122 + if (w[high] > wavelength) break;
  123 + }
  124 + low = 0;
  125 + if (high > 0)
  126 + low = high - 1;
  127 + }
  128 +
  129 + /// Get the list of band numbers that bound a list of wavelengths
  130 + void band_bounds(std::vector<double> wavelengths,
  131 + std::vector<unsigned long long>& low_bands,
  132 + std::vector<unsigned long long>& high_bands) {
  133 +
  134 + unsigned long long W = w.size(); //get the number of wavelengths in the list
  135 + low_bands.resize(W); //pre-allocate space for the band lists
  136 + high_bands.resize(W);
  137 +
  138 + for (unsigned long long wl = 0; wl < W; wl++) { //for each wavelength
  139 + band_bounds(wavelengths[wl], low_bands[wl], high_bands[wl]); //find the low and high bands
  140 + }
  141 + }
142 /// Get a mask that has all pixels with inf or NaN values masked out (false) 142 /// Get a mask that has all pixels with inf or NaN values masked out (false)
143 void mask_finite(unsigned char* out_mask, unsigned char* mask, bool PROGRESS = false){ 143 void mask_finite(unsigned char* out_mask, unsigned char* mask, bool PROGRESS = false){
144 size_t XY = X() * Y(); 144 size_t XY = X() * Y();
stim/math/matrix.h
@@ -33,32 +33,58 @@ namespace stim{ @@ -33,32 +33,58 @@ namespace stim{
33 } 33 }
34 } 34 }
35 35
  36 + //class encapsulates a mat4 file, and can be used to write multiple matrices to a single mat4 file
  37 + class mat4file {
  38 + std::ofstream matfile;
  39 +
  40 + public:
  41 + /// Constructor opens a mat4 file for writing
  42 + mat4file(std::string filename) {
  43 + matfile.open(filename, std::ios::binary);
  44 + }
  45 +
  46 + bool is_open() {
  47 + return matfile.is_open();
  48 + }
  49 +
  50 + void close() {
  51 + matfile.close();
  52 + }
  53 +
  54 + bool writemat(char* data, std::string varname, size_t sx, size_t sy, mat4Format format) {
  55 + //save the matrix file here (use the mat4 function above)
  56 + //data format: https://maxwell.ict.griffith.edu.au/spl/matlab-page/matfile_format.pdf (page 32)
  57 +
  58 + int MOPT = 0; //initialize the MOPT type value to zero
  59 + int m = 0; //little endian
  60 + int o = 0; //reserved, always 0
  61 + int p = format;
  62 + int t = 0;
  63 + MOPT = m * 1000 + o * 100 + p * 10 + t; //calculate the type value
  64 + int mrows = (int)sx;
  65 + int ncols = (int)sy;
  66 + int imagf = 0; //assume real (for now)
  67 + varname.push_back('\0'); //add a null to the string
  68 + int namlen = (int)varname.size(); //calculate the name size
  69 +
  70 + size_t bytes = sx * sy * mat4Format_size(format);
  71 + matfile.write((char*)&MOPT, 4);
  72 + matfile.write((char*)&mrows, 4);
  73 + matfile.write((char*)&ncols, 4);
  74 + matfile.write((char*)&imagf, 4);
  75 + matfile.write((char*)&namlen, 4);
  76 + matfile.write((char*)&varname[0], namlen);
  77 + matfile.write((char*)data, bytes); //write the matrix data
  78 + return is_open();
  79 + }
  80 + };
  81 +
36 static void save_mat4(char* data, std::string filename, std::string varname, size_t sx, size_t sy, mat4Format format){ 82 static void save_mat4(char* data, std::string filename, std::string varname, size_t sx, size_t sy, mat4Format format){
37 - //save the matrix file here (use the mat4 function above)  
38 - //data format: https://maxwell.ict.griffith.edu.au/spl/matlab-page/matfile_format.pdf (page 32)  
39 -  
40 - int MOPT = 0; //initialize the MOPT type value to zero  
41 - int m = 0; //little endian  
42 - int o = 0; //reserved, always 0  
43 - int p = format;  
44 - int t = 0;  
45 - MOPT = m * 1000 + o * 100 + p * 10 + t; //calculate the type value  
46 - int mrows = (int)sx;  
47 - int ncols = (int)sy;  
48 - int imagf = 0; //assume real (for now)  
49 - varname.push_back('\0'); //add a null to the string  
50 - int namlen = (int)varname.size(); //calculate the name size  
51 -  
52 - size_t bytes = sx * sy * mat4Format_size(format);  
53 - std::ofstream outfile(filename, std::ios::binary);  
54 - outfile.write((char*)&MOPT, 4);  
55 - outfile.write((char*)&mrows, 4);  
56 - outfile.write((char*)&ncols, 4);  
57 - outfile.write((char*)&imagf, 4);  
58 - outfile.write((char*)&namlen, 4);  
59 - outfile.write((char*)&varname[0], namlen);  
60 - outfile.write((char*)data, bytes); //write the matrix data  
61 - outfile.close(); 83 + mat4file outfile(filename); //create a mat4 file object
  84 + if (outfile.is_open()) { //if the file is open
  85 + outfile.writemat(data, varname, sx, sy, format); //write the matrix
  86 + outfile.close(); //close the file
  87 + }
62 } 88 }
63 89
64 template <class T> 90 template <class T>
@@ -409,8 +435,21 @@ public: @@ -409,8 +435,21 @@ public:
409 } 435 }
410 } 436 }
411 437
412 - // saves the matrix as a Level-4 MATLAB file  
413 - void mat4(std::string filename, std::string name = std::string("unknown"), mat4Format format = mat4_float) { 438 + void mat4(stim::mat4file& file, std::string name = std::string("unknown"), mat4Format format = mat4_float) {
  439 + //make sure the matrix name is valid (only numbers and letters, with a letter at the beginning
  440 + for (size_t c = 0; c < name.size(); c++) {
  441 + if (name[c] < 48 || //if the character isn't a number or letter, replace it with '_'
  442 + (name[c] > 57 && name[c] < 65) ||
  443 + (name[c] > 90 && name[c] < 97) ||
  444 + (name[c] > 122)) {
  445 + name[c] = '_';
  446 + }
  447 + }
  448 + if (name[0] < 65 ||
  449 + (name[0] > 91 && name[0] < 97) ||
  450 + name[0] > 122) {
  451 + name = std::string("m") + name;
  452 + }
414 if (format == mat4_float) { 453 if (format == mat4_float) {
415 if (sizeof(T) == 4) format = mat4_float32; 454 if (sizeof(T) == 4) format = mat4_float32;
416 else if (sizeof(T) == 8) format = mat4_float64; 455 else if (sizeof(T) == 8) format = mat4_float64;
@@ -419,7 +458,40 @@ public: @@ -419,7 +458,40 @@ public:
419 exit(1); 458 exit(1);
420 } 459 }
421 } 460 }
422 - stim::save_mat4((char*)M, filename, name, rows(), cols(), format); 461 + //the name is now valid
  462 +
  463 + //if the size of the array is more than 100,000,000 elements, the matrix isn't supported
  464 + if (rows() * cols() > 100000000) { //break the matrix up into multiple parts
  465 + //mat4file out(filename); //create a mat4 object to write the matrix
  466 + if (file.is_open()) {
  467 + if (rows() < 100000000) { //if the size of the row is less than 100,000,000, split the matrix up by columns
  468 + size_t ncols = 100000000 / rows(); //calculate the number of columns that can fit in one matrix
  469 + size_t nmat = (size_t)std::ceil((double)cols() / (double)ncols); //calculate the number of matrices required
  470 + for (size_t m = 0; m < nmat; m++) { //for each matrix
  471 + std::stringstream ss;
  472 + ss << name << "_part_" << m + 1;
  473 + if (m == nmat - 1)
  474 + file.writemat((char*)(data() + m * ncols * rows()), ss.str(), rows(), cols() - m * ncols, format);
  475 + else
  476 + file.writemat((char*)(data() + m * ncols * rows()), ss.str(), rows(), ncols, format);
  477 + }
  478 + }
  479 + }
  480 + }
  481 + //call the mat4 subroutine
  482 + else
  483 + //stim::save_mat4((char*)M, filename, name, rows(), cols(), format);
  484 + file.writemat((char*)data(), name, rows(), cols(), format);
  485 + }
  486 +
  487 + // saves the matrix as a Level-4 MATLAB file
  488 + void mat4(std::string filename, std::string name = std::string("unknown"), mat4Format format = mat4_float) {
  489 + stim::mat4file matfile(filename);
  490 +
  491 + if (matfile.is_open()) {
  492 + mat4(matfile, name, format);
  493 + matfile.close();
  494 + }
423 } 495 }
424 }; 496 };
425 497