Commit ba51ae6a3d666879ecea0dd9fe40a56b7ca47092

Authored by David Mayerich
1 parent 44f44bb5

fixed metric calculations, added a finite-value mask, as_float() in stim::arglist returns a double

@@ -600,7 +600,7 @@ public: @@ -600,7 +600,7 @@ public:
600 /// @param rb2 is the label value for the right baseline point for the second peak (denominator) 600 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
601 /// @param pos2 is the label value for the second peak (denominator) position 601 /// @param pos2 is the label value for the second peak (denominator) position
602 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 602 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
603 - bool ph_to_ph(double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, T * result){ 603 + bool ph_to_ph(T* result, double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, unsigned char* mask = NULL){
604 604
605 T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 605 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
606 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 606 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
@@ -630,8 +630,8 @@ public: @@ -630,8 +630,8 @@ public:
630 /// @param rb2 is the label value for the right baseline point for the second peak (denominator) 630 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
631 /// @param pos2 is the label value for the second peak (denominator) position 631 /// @param pos2 is the label value for the second peak (denominator) position
632 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 632 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
633 - bool pa_to_ph(double lb1, double rb1, double lab1, double rab1,  
634 - double lb2, double rb2, double pos, T* result){ 633 + bool pa_to_ph(T* result, double lb1, double rb1, double lab1, double rab1,
  634 + double lb2, double rb2, double pos, unsigned char* mask = NULL){
635 635
636 T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 636 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
637 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 637 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
@@ -663,8 +663,8 @@ public: @@ -663,8 +663,8 @@ public:
663 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator) 663 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
664 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator) 664 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
665 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 665 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
666 - bool pa_to_pa(double lb1, double rb1, double lab1, double rab1,  
667 - double lb2, double rb2, double lab2, double rab2, T* result){ 666 + bool pa_to_pa(T* result, double lb1, double rb1, double lab1, double rab1,
  667 + double lb2, double rb2, double lab2, double rab2, unsigned char* mask = NULL){
668 668
669 T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 669 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
670 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 670 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
@@ -773,7 +773,7 @@ public: @@ -773,7 +773,7 @@ public:
773 /// @param lab is the label for the start of the peak 773 /// @param lab is the label for the start of the peak
774 /// @param rab is the label for the end of the peak 774 /// @param rab is the label for the end of the peak
775 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 775 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
776 - bool cpoint(double lb, double rb, double lab, double rab, T* result){ 776 + bool centroid(T* result, double lb, double rb, double lab, double rab, unsigned char* mask = NULL){
777 T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 777 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
778 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 778 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
779 779
@@ -782,9 +782,7 @@ public: @@ -782,9 +782,7 @@ public:
782 area(lb, rb, lab, rab, p2); 782 area(lb, rb, lab, rab, p2);
783 //calculate the ratio in result 783 //calculate the ratio in result
784 for(unsigned long long i = 0; i < X() * Y(); i++){ 784 for(unsigned long long i = 0; i < X() * Y(); i++){
785 - if(p1[i] == 0 && p2[i] ==0)  
786 - result[i] = 1;  
787 - else 785 + if(mask == NULL || mask[i])
788 result[i] = p1[i] / p2[i]; 786 result[i] = p1[i] / p2[i];
789 } 787 }
790 788
@@ -800,16 +798,16 @@ public: @@ -800,16 +798,16 @@ public:
800 /// @param mask_band is the band used to specify the mask 798 /// @param mask_band is the band used to specify the mask
801 /// @param threshold is the threshold used to determine if the mask value is true or false 799 /// @param threshold is the threshold used to determine if the mask value is true or false
802 /// @param p is a pointer to a pre-allocated array at least X * Y in size 800 /// @param p is a pointer to a pre-allocated array at least X * Y in size
803 - bool build_mask(double mask_band, double threshold, unsigned char* p, bool PROGRESS = false){ 801 + bool build_mask(unsigned char* mask, double mask_band, double threshold, bool PROGRESS = false){
804 802
805 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band 803 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
806 band(temp, mask_band, PROGRESS); 804 band(temp, mask_band, PROGRESS);
807 805
808 for (unsigned long long i = 0; i < X() * Y(); i++) { 806 for (unsigned long long i = 0; i < X() * Y(); i++) {
809 if (temp[i] < threshold) 807 if (temp[i] < threshold)
810 - p[i] = 0; 808 + mask[i] = 0;
811 else 809 else
812 - p[i] = 255; 810 + mask[i] = 255;
813 } 811 }
814 812
815 free(temp); 813 free(temp);
@@ -850,6 +848,36 @@ public: @@ -850,6 +848,36 @@ public:
850 return true; 848 return true;
851 } 849 }
852 850
  851 + /// Copies all spectra corresponding to nonzero values of a mask into a pre-allocated matrix of size (B x P)
  852 + /// where P is the number of masked pixels and B is the number of bands. The allocated memory can be accessed
  853 + /// using the following indexing: i = p*B + b
  854 + /// @param matrix is the destination for the pixel data
  855 + /// @param mask is the mask
  856 + bool sift(T* matrix, unsigned char* mask){
  857 + size_t Lbytes = sizeof(T) * X();
  858 + T* line = (T*) malloc( Lbytes ); //allocate space for a line
  859 +
  860 + file.seekg(0, std::ios::beg); //seek to the beginning of the file
  861 +
  862 + size_t pl;
  863 + size_t p = 0; //create counter variables
  864 + for(size_t y = 0; y < Y(); y++){ //for each line in the data set
  865 + for(size_t b = 0; b < Z(); b++){ //for each band in the data set
  866 + pl = 0; //initialize the pixel offset for the current line to zero (0)
  867 + file.read( (char*)line, Lbytes ); //read the current line
  868 + for(size_t x = 0; x < X(); x++){
  869 + if(mask[y * X() + x]){ //if the current pixel is masked
  870 + size_t i = (p + pl) * Z() + b; //calculate the index in the sifted matrix
  871 + matrix[i] = line[x]; //store the current value in the line at the correct matrix location
  872 + pl++; //increment the pixel pointer
  873 + }
  874 + }
  875 + }
  876 + p += pl; //add the line increment to the running pixel index
  877 + }
  878 + return true;
  879 + }
  880 +
853 /// Saves to disk only those spectra corresponding to mask values != 0 881 /// Saves to disk only those spectra corresponding to mask values != 0
854 /// Unlike the BIP and BSQ versions of this function, this version saves a different format: the BIL file is saved as a BIP 882 /// Unlike the BIP and BSQ versions of this function, this version saves a different format: the BIL file is saved as a BIP
855 bool sift(std::string outfile, unsigned char* p, bool PROGRESS = false){ 883 bool sift(std::string outfile, unsigned char* p, bool PROGRESS = false){
@@ -526,7 +526,7 @@ public: @@ -526,7 +526,7 @@ public:
526 /// @param rb2 is the label value for the right baseline point for the second peak (denominator) 526 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
527 /// @param pos2 is the label value for the second peak (denominator) position 527 /// @param pos2 is the label value for the second peak (denominator) position
528 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 528 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
529 - bool ph_to_ph(double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, T * result){ 529 + bool ph_to_ph(T* result, double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, unsigned char* mask = NULL){
530 530
531 T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 531 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
532 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 532 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
@@ -556,8 +556,8 @@ public: @@ -556,8 +556,8 @@ public:
556 /// @param rb2 is the label value for the right baseline point for the second peak (denominator) 556 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
557 /// @param pos2 is the label value for the second peak (denominator) position 557 /// @param pos2 is the label value for the second peak (denominator) position
558 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 558 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
559 - bool pa_to_ph(double lb1, double rb1, double lab1, double rab1,  
560 - double lb2, double rb2, double pos, T* result){ 559 + bool pa_to_ph(T* result, double lb1, double rb1, double lab1, double rab1,
  560 + double lb2, double rb2, double pos, unsigned char* mask = NULL){
561 561
562 T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 562 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
563 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 563 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
@@ -589,8 +589,8 @@ public: @@ -589,8 +589,8 @@ public:
589 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator) 589 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
590 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator) 590 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
591 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 591 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
592 - bool pa_to_pa(double lb1, double rb1, double lab1, double rab1,  
593 - double lb2, double rb2, double lab2, double rab2, T* result){ 592 + bool pa_to_pa(T* result, double lb1, double rb1, double lab1, double rab1,
  593 + double lb2, double rb2, double lab2, double rab2, unsigned char* mask = NULL){
594 594
595 T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 595 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
596 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 596 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
@@ -699,7 +699,7 @@ public: @@ -699,7 +699,7 @@ public:
699 /// @param lab is the label for the start of the peak 699 /// @param lab is the label for the start of the peak
700 /// @param rab is the label for the end of the peak 700 /// @param rab is the label for the end of the peak
701 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 701 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
702 - bool cpoint(double lb, double rb, double lab, double rab, T* result){ 702 + bool centroid(T* result, double lb, double rb, double lab, double rab, unsigned char* mask = NULL){
703 T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 703 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
704 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 704 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
705 705
@@ -708,9 +708,7 @@ public: @@ -708,9 +708,7 @@ public:
708 area(lb, rb, lab, rab, p2); 708 area(lb, rb, lab, rab, p2);
709 //calculate the ratio in result 709 //calculate the ratio in result
710 for(unsigned long long i = 0; i < X() * Y(); i++){ 710 for(unsigned long long i = 0; i < X() * Y(); i++){
711 - if(p1[i] == 0 && p2[i] ==0)  
712 - result[i] = 1;  
713 - else 711 + if(mask == NULL || mask[i])
714 result[i] = p1[i] / p2[i]; 712 result[i] = p1[i] / p2[i];
715 } 713 }
716 714
@@ -726,16 +724,16 @@ public: @@ -726,16 +724,16 @@ public:
726 /// @param mask_band is the band used to specify the mask 724 /// @param mask_band is the band used to specify the mask
727 /// @param threshold is the threshold used to determine if the mask value is true or false 725 /// @param threshold is the threshold used to determine if the mask value is true or false
728 /// @param p is a pointer to a pre-allocated array at least X * Y in size 726 /// @param p is a pointer to a pre-allocated array at least X * Y in size
729 - bool build_mask(double mask_band, double threshold, unsigned char* p, bool PROGRESS = false){ 727 + bool build_mask(unsigned char* mask, double mask_band, double threshold, bool PROGRESS = false){
730 728
731 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band 729 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
732 band(temp, mask_band, PROGRESS); 730 band(temp, mask_band, PROGRESS);
733 731
734 for (unsigned long long i = 0; i < X() * Y();i++) { 732 for (unsigned long long i = 0; i < X() * Y();i++) {
735 if (temp[i] < threshold) 733 if (temp[i] < threshold)
736 - p[i] = 0; 734 + mask[i] = 0;
737 else 735 else
738 - p[i] = 255; 736 + mask[i] = 255;
739 } 737 }
740 738
741 free(temp); 739 free(temp);
@@ -776,6 +774,33 @@ public: @@ -776,6 +774,33 @@ public:
776 return true; //return true 774 return true; //return true
777 } 775 }
778 776
  777 + /// Copies all spectra corresponding to nonzero values of a mask into a pre-allocated matrix of size (B x P)
  778 + /// where P is the number of masked pixels and B is the number of bands. The allocated memory can be accessed
  779 + /// using the following indexing: i = p*B + b
  780 + /// @param matrix is the destination for the pixel data
  781 + /// @param mask is the mask
  782 + bool sift(T* matrix, unsigned char* mask){
  783 + size_t Bbytes = sizeof(T) * Z();
  784 + size_t XY = X() * Y();
  785 + T* band = (T*) malloc( Bbytes ); //allocate space for a line
  786 +
  787 + file.seekg(0, std::ios::beg); //seek to the beginning of the file
  788 +
  789 + size_t p = 0; //create counter variables
  790 + for(size_t xy = 0; xy < XY; xy++){ //for each pixel
  791 + if(mask[xy]){ //if the current pixel is masked
  792 + file.read( (char*)band, Bbytes ); //read the current line
  793 + for(size_t b = 0; b < Z(); b++){ //copy each band value to the sifted matrix
  794 + size_t i = p * Z() + b; //calculate the index in the sifted matrix
  795 + matrix[i] = band[b]; //store the current value in the line at the correct matrix location
  796 + }
  797 + p++; //increment the pixel pointer
  798 + }
  799 + else
  800 + file.seekg(Bbytes, std::ios::cur); //otherwise skip this band
  801 + }
  802 + return true;
  803 + }
779 804
780 /// Saves to disk only those spectra corresponding to mask values != 0 805 /// Saves to disk only those spectra corresponding to mask values != 0
781 bool sift(std::string outfile, unsigned char* mask, bool PROGRESS = false){ 806 bool sift(std::string outfile, unsigned char* mask, bool PROGRESS = false){
@@ -436,9 +436,7 @@ public: @@ -436,9 +436,7 @@ public:
436 cur = (T*) malloc(S); 436 cur = (T*) malloc(S);
437 cur2 = (T*) malloc(S); 437 cur2 = (T*) malloc(S);
438 438
439 - memset(result, (char)0, S);  
440 -  
441 - //find the wavelenght position in the whole band 439 + //find the wavelength position in the whole band
442 unsigned long long n = w.size(); 440 unsigned long long n = w.size();
443 unsigned long long ai = 0; //left bound position 441 unsigned long long ai = 0; //left bound position
444 unsigned long long bi = n - 1; //right bound position 442 unsigned long long bi = n - 1; //right bound position
@@ -450,26 +448,30 @@ public: @@ -450,26 +448,30 @@ public:
450 std::cout<<"ERROR: left bound or right bound out of bandwidth"<<std::endl; 448 std::cout<<"ERROR: left bound or right bound out of bandwidth"<<std::endl;
451 exit(1); 449 exit(1);
452 } 450 }
453 - //to make sure rigth bound is bigger than left bound 451 + //to make sure right bound is bigger than left bound
454 else if(lb > rb){ 452 else if(lb > rb){
455 std::cout<<"ERROR: right bound should be bigger than left bound"<<std::endl; 453 std::cout<<"ERROR: right bound should be bigger than left bound"<<std::endl;
456 exit(1); 454 exit(1);
457 } 455 }
458 456
459 - //get the position of lb and rb  
460 - while (lab >= w[ai]){ 457 + //find the indices of the left and right baseline points
  458 + while (lab >= w[ai]){
461 ai++; 459 ai++;
462 } 460 }
463 while (rab <= w[bi]){ 461 while (rab <= w[bi]){
464 bi--; 462 bi--;
465 } 463 }
466 464
467 - band(lp, lb); 465 + band(lp, lb); //get the band images for the left and right baseline points
468 band(rp, rb); 466 band(rp, rb);
469 467
470 - //calculate the beginning and the ending part  
471 - baseline_band(lb, rb, lp, rp, rab, cur2); //ending part  
472 - baseline_band(lb, rb, lp, rp, w[bi], cur); 468 + // calculate the average value of the indexed region
  469 + memset(result, 0, S); //initialize the integral to zero (0)
  470 +
  471 + //integrate the region between the specified bands and the closest indexed band
  472 + // this integrates the "tails" of the spectrum that lie outside the main indexed region
  473 + baseline_band(lb, rb, lp, rp, rab, cur2); //calculate the image for the right-most band in the integral
  474 + baseline_band(lb, rb, lp, rp, w[bi], cur); //calculate the image for the right-most indexed band
473 for(unsigned long long j = 0; j < XY; j++){ 475 for(unsigned long long j = 0; j < XY; j++){
474 result[j] += (T)((rab - w[bi]) * ((double)cur[j] + (double)cur2[j]) / 2.0); 476 result[j] += (T)((rab - w[bi]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
475 } 477 }
@@ -479,13 +481,12 @@ public: @@ -479,13 +481,12 @@ public:
479 result[j] += (T)((w[ai] - lab) * ((double)cur[j] + (double)cur2[j]) / 2.0); 481 result[j] += (T)((w[ai] - lab) * ((double)cur[j] + (double)cur2[j]) / 2.0);
480 } 482 }
481 483
482 - //calculate the area 484 + //integrate the main indexed region
483 ai++; 485 ai++;
484 - for(unsigned long long i = ai; i <= bi ;i++) 486 + for(unsigned long long i = ai; i <= bi ;i++) //for each band in the integral
485 { 487 {
486 - baseline_band(lb, rb, lp, rp, w[ai], cur2);  
487 - for(unsigned long long j = 0; j < XY; j++)  
488 - { 488 + baseline_band(lb, rb, lp, rp, w[ai], cur2); //get the baselined band
  489 + for(unsigned long long j = 0; j < XY; j++){ //for each pixel in that band
489 result[j] += (T)((w[ai] - w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 2.0); 490 result[j] += (T)((w[ai] - w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
490 } 491 }
491 std::swap(cur,cur2); //swap the band pointers 492 std::swap(cur,cur2); //swap the band pointers
@@ -507,20 +508,22 @@ public: @@ -507,20 +508,22 @@ public:
507 /// @param rb2 is the label value for the right baseline point for the second peak (denominator) 508 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
508 /// @param pos2 is the label value for the second peak (denominator) position 509 /// @param pos2 is the label value for the second peak (denominator) position
509 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 510 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
510 - bool ph_to_ph(double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, T * result){ 511 + bool ph_to_ph(T* result, double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, unsigned char* mask = NULL){
511 512
512 - T* p1 = (T*)malloc(X() * Y() * sizeof(T));  
513 - T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 513 + size_t XYbytes = X() * Y() * sizeof(T); //calculate the size of the band image (in bytes)
  514 +
  515 + T* p1 = (T*)malloc(XYbytes); //allocate space for both bands in the ratio
  516 + T* p2 = (T*)malloc(XYbytes);
514 517
  518 + memset(result, 0, XYbytes); //initialize the ratio to zero
515 //get the two peak band 519 //get the two peak band
516 height(lb1, rb1, pos1, p1); 520 height(lb1, rb1, pos1, p1);
517 height(lb2, rb2, pos2, p2); 521 height(lb2, rb2, pos2, p2);
518 //calculate the ratio in result 522 //calculate the ratio in result
519 for(unsigned long long i = 0; i < X() * Y(); i++){ 523 for(unsigned long long i = 0; i < X() * Y(); i++){
520 - if(p1[i] == 0 && p2[i] ==0)  
521 - result[i] = 1;  
522 - else 524 + if(mask == NULL || mask[i]){
523 result[i] = p1[i] / p2[i]; 525 result[i] = p1[i] / p2[i];
  526 + }
524 } 527 }
525 528
526 free(p1); 529 free(p1);
@@ -537,20 +540,20 @@ public: @@ -537,20 +540,20 @@ public:
537 /// @param rb2 is the label value for the right baseline point for the second peak (denominator) 540 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
538 /// @param pos2 is the label value for the second peak (denominator) position 541 /// @param pos2 is the label value for the second peak (denominator) position
539 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 542 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
540 - bool pa_to_ph(double lb1, double rb1, double lab1, double rab1,  
541 - double lb2, double rb2, double pos, T* result){ 543 + bool pa_to_ph(T* result, double lb1, double rb1, double lab1, double rab1,
  544 + double lb2, double rb2, double pos, unsigned char* mask = NULL){
542 545
543 - T* p1 = (T*)malloc(X() * Y() * sizeof(T));  
544 - T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 546 + size_t bytes = X() * Y() * sizeof(T);
  547 + T* p1 = (T*)malloc(bytes); //allocate space for both ratio components
  548 + T* p2 = (T*)malloc(bytes);
545 549
  550 + memset(result, 0, bytes); //initialize the ratio to zero
546 //get the area and the peak band 551 //get the area and the peak band
547 area(lb1, rb1, lab1, rab1, p1); 552 area(lb1, rb1, lab1, rab1, p1);
548 height(lb2, rb2, pos, p2); 553 height(lb2, rb2, pos, p2);
549 //calculate the ratio in result 554 //calculate the ratio in result
550 for(unsigned long long i = 0; i < X() * Y(); i++){ 555 for(unsigned long long i = 0; i < X() * Y(); i++){
551 - if(p1[i] == 0 && p2[i] ==0)  
552 - result[i] = 1;  
553 - else 556 + if(mask == NULL || mask[i])
554 result[i] = p1[i] / p2[i]; 557 result[i] = p1[i] / p2[i];
555 } 558 }
556 559
@@ -570,21 +573,21 @@ public: @@ -570,21 +573,21 @@ public:
570 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator) 573 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
571 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator) 574 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
572 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 575 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
573 - bool pa_to_pa(double lb1, double rb1, double lab1, double rab1,  
574 - double lb2, double rb2, double lab2, double rab2, T* result){ 576 + bool pa_to_pa(T* result, double lb1, double rb1, double lab1, double rab1,
  577 + double lb2, double rb2, double lab2, double rab2, unsigned char* mask = NULL){
575 578
576 - T* p1 = (T*)malloc(X() * Y() * sizeof(T));  
577 - T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 579 + size_t bytes = X() * Y() * sizeof(T);
  580 + T* p1 = (T*)malloc(bytes); //allocate space for each of the operands
  581 + T* p2 = (T*)malloc(bytes);
578 582
  583 + memset(result, 0, bytes); //initialize the ratio result to zero (0)
579 //get the area and the peak band 584 //get the area and the peak band
580 area(lb1, rb1, lab1, rab1, p1); 585 area(lb1, rb1, lab1, rab1, p1);
581 area(lb2, rb2, lab2, rab2, p2); 586 area(lb2, rb2, lab2, rab2, p2);
582 //calculate the ratio in result 587 //calculate the ratio in result
583 for(unsigned long long i = 0; i < X() * Y(); i++){ 588 for(unsigned long long i = 0; i < X() * Y(); i++){
584 - if(p1[i] == 0 && p2[i] ==0)  
585 - result[i] = 1;  
586 - else  
587 - result[i] = p1[i] / p2[i]; 589 + if(mask == NULL || mask[i]) //if the pixel is masked
  590 + result[i] = p1[i] / p2[i]; //calculate the ratio
588 } 591 }
589 592
590 free(p1); 593 free(p1);
@@ -592,7 +595,7 @@ public: @@ -592,7 +595,7 @@ public:
592 return true; 595 return true;
593 } 596 }
594 597
595 - /// Compute the definite integral of a baseline corrected peak. 598 + /// Compute the definite integral of a baseline corrected peak weighted by the corresponding wavelength
596 599
597 /// @param lb is the label value for the left baseline point 600 /// @param lb is the label value for the left baseline point
598 /// @param rb is the label value for the right baseline point 601 /// @param rb is the label value for the right baseline point
@@ -613,8 +616,6 @@ public: @@ -613,8 +616,6 @@ public:
613 cur = (T*) malloc(S); 616 cur = (T*) malloc(S);
614 cur2 = (T*) malloc(S); 617 cur2 = (T*) malloc(S);
615 618
616 - memset(result, (char)0, S);  
617 -  
618 //find the wavelenght position in the whole band 619 //find the wavelenght position in the whole band
619 unsigned long long n = w.size(); 620 unsigned long long n = w.size();
620 unsigned long long ai = 0; //left bound position 621 unsigned long long ai = 0; //left bound position
@@ -642,6 +643,8 @@ public: @@ -642,6 +643,8 @@ public:
642 band(lp, lb); 643 band(lp, lb);
643 band(rp, rb); 644 band(rp, rb);
644 645
  646 + memset(result, (char)0, S); //initialize the integral to zero (0)
  647 +
645 //calculate the beginning and the ending part 648 //calculate the beginning and the ending part
646 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part 649 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part
647 baseline_band(lb, rb, lp, rp, w[bi], cur); 650 baseline_band(lb, rb, lp, rp, w[bi], cur);
@@ -656,12 +659,11 @@ public: @@ -656,12 +659,11 @@ public:
656 659
657 //calculate f(x) times x 660 //calculate f(x) times x
658 ai++; 661 ai++;
659 - for(unsigned long long i = ai; i <= bi ;i++)  
660 - { 662 + for(unsigned long long i = ai; i <= bi ;i++){
661 baseline_band(lb, rb, lp, rp, w[ai], cur2); 663 baseline_band(lb, rb, lp, rp, w[ai], cur2);
662 - for(unsigned long long j = 0; j < XY; j++)  
663 - {  
664 - result[j] += (T)((w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 4.0); 664 + for(unsigned long long j = 0; j < XY; j++){
  665 + T v = (T)((w[ai] - w[ai-1]) * (w[ai] + w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 4.0);
  666 + result[j] += v;
665 } 667 }
666 std::swap(cur,cur2); //swap the band pointers 668 std::swap(cur,cur2); //swap the band pointers
667 } 669 }
@@ -674,25 +676,27 @@ public: @@ -674,25 +676,27 @@ public:
674 } 676 }
675 677
676 /// Compute the centroid of a baseline corrected peak. 678 /// Compute the centroid of a baseline corrected peak.
  679 + /// Note that the values for the centroid can be outside of [lab, rab] if the spectrum goes negative.
677 680
678 /// @param lb is the label value for the left baseline point 681 /// @param lb is the label value for the left baseline point
679 /// @param rb is the label value for the right baseline point 682 /// @param rb is the label value for the right baseline point
680 /// @param lab is the label for the start of the peak 683 /// @param lab is the label for the start of the peak
681 /// @param rab is the label for the end of the peak 684 /// @param rab is the label for the end of the peak
682 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 685 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
683 - bool cpoint(double lb, double rb, double lab, double rab, T* result){  
684 - T* p1 = (T*)malloc(X() * Y() * sizeof(T)); 686 + bool centroid(T* result, double lb, double rb, double lab, double rab, unsigned char* mask = NULL){
  687 + size_t bytes = X() * Y() * sizeof(T); //calculate the number of bytes in a band image
  688 + T* p1 = (T*)malloc(X() * Y() * sizeof(T)); //allocate space for both operands
685 T* p2 = (T*)malloc(X() * Y() * sizeof(T)); 689 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
686 690
  691 + memset(result, 0, bytes); //initialize the ratio result to zero (0)
687 //get the area and the peak band 692 //get the area and the peak band
688 x_area(lb, rb, lab, rab, p1); 693 x_area(lb, rb, lab, rab, p1);
689 area(lb, rb, lab, rab, p2); 694 area(lb, rb, lab, rab, p2);
690 //calculate the ratio in result 695 //calculate the ratio in result
691 for(unsigned long long i = 0; i < X() * Y(); i++){ 696 for(unsigned long long i = 0; i < X() * Y(); i++){
692 - if(p1[i] == 0 && p2[i] ==0)  
693 - result[i] = 1;  
694 - else 697 + if(mask == NULL || mask[i]){
695 result[i] = p1[i] / p2[i]; 698 result[i] = p1[i] / p2[i];
  699 + }
696 } 700 }
697 701
698 free(p1); 702 free(p1);
@@ -707,16 +711,16 @@ public: @@ -707,16 +711,16 @@ public:
707 /// @param mask_band is the band used to specify the mask 711 /// @param mask_band is the band used to specify the mask
708 /// @param threshold is the threshold used to determine if the mask value is true or false 712 /// @param threshold is the threshold used to determine if the mask value is true or false
709 /// @param p is a pointer to a pre-allocated array at least X * Y in size 713 /// @param p is a pointer to a pre-allocated array at least X * Y in size
710 - bool build_mask(double mask_band, double threshold, unsigned char* p = NULL, bool PROGRESS = false){ 714 + bool build_mask(unsigned char* mask, double mask_band, double threshold, bool PROGRESS = false){
711 715
712 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band 716 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
713 band(temp, mask_band); 717 band(temp, mask_band);
714 718
715 for (unsigned long long i = 0; i < X() * Y(); i++) { 719 for (unsigned long long i = 0; i < X() * Y(); i++) {
716 if (temp[i] < threshold) 720 if (temp[i] < threshold)
717 - p[i] = 0; 721 + mask[i] = 0;
718 else 722 else
719 - p[i] = 255; 723 + mask[i] = 255;
720 724
721 if(PROGRESS) progress = (double) (i+1) / (X() * Y()) * 100; 725 if(PROGRESS) progress = (double) (i+1) / (X() * Y()) * 100;
722 } 726 }
@@ -475,31 +475,31 @@ public: @@ -475,31 +475,31 @@ public:
475 /// @param mask_band is the label for the band that will be used to build the mask 475 /// @param mask_band is the label for the band that will be used to build the mask
476 /// @param threshold is a value selected such that all band values greater than threshold will have a mask value of 'true' 476 /// @param threshold is a value selected such that all band values greater than threshold will have a mask value of 'true'
477 /// @param p is memory of size X*Y that will store the resulting mask 477 /// @param p is memory of size X*Y that will store the resulting mask
478 - bool build_mask(double mask_band, double threshold, unsigned char* p = NULL, bool PROGRESS = false) { 478 + bool build_mask(unsigned char* mask, double mask_band, double threshold, bool PROGRESS = false) {
479 479
480 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 480 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
481 if(header.data_type ==envi_header::float32) 481 if(header.data_type ==envi_header::float32)
482 - return ((bsq<float>*)file)->build_mask(mask_band, threshold, p, PROGRESS); 482 + return ((bsq<float>*)file)->build_mask(mask, mask_band, threshold, PROGRESS);
483 else if(header.data_type == envi_header::float64) 483 else if(header.data_type == envi_header::float64)
484 - return ((bsq<double>*)file)->build_mask(mask_band, threshold, p, PROGRESS); 484 + return ((bsq<double>*)file)->build_mask(mask, mask_band, threshold, PROGRESS);
485 else 485 else
486 std::cout<<"ERROR: unidentified data type"<<std::endl; 486 std::cout<<"ERROR: unidentified data type"<<std::endl;
487 } 487 }
488 488
489 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 489 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
490 if(header.data_type ==envi_header::float32) 490 if(header.data_type ==envi_header::float32)
491 - return ((bil<float>*)file)->build_mask(mask_band, threshold, p, PROGRESS); 491 + return ((bil<float>*)file)->build_mask(mask, mask_band, threshold, PROGRESS);
492 else if(header.data_type == envi_header::float64) 492 else if(header.data_type == envi_header::float64)
493 - return ((bil<double>*)file)->build_mask(mask_band, threshold, p, PROGRESS); 493 + return ((bil<double>*)file)->build_mask(mask, mask_band, threshold, PROGRESS);
494 else 494 else
495 std::cout<<"ERROR: unidentified data type"<<std::endl; 495 std::cout<<"ERROR: unidentified data type"<<std::endl;
496 } 496 }
497 497
498 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 498 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
499 if(header.data_type ==envi_header::float32) 499 if(header.data_type ==envi_header::float32)
500 - return ((bip<float>*)file)->build_mask(mask_band, threshold, p, PROGRESS); 500 + return ((bip<float>*)file)->build_mask(mask, mask_band, threshold, PROGRESS);
501 else if(header.data_type == envi_header::float64) 501 else if(header.data_type == envi_header::float64)
502 - return ((bip<double>*)file)->build_mask(mask_band, threshold, p, PROGRESS); 502 + return ((bip<double>*)file)->build_mask(mask, mask_band, threshold, PROGRESS);
503 else 503 else
504 std::cout<<"ERROR: unidentified data type"<<std::endl; 504 std::cout<<"ERROR: unidentified data type"<<std::endl;
505 } 505 }
@@ -507,6 +507,36 @@ public: @@ -507,6 +507,36 @@ public:
507 return false; 507 return false;
508 } 508 }
509 509
  510 + /// Creates a mask with a true value for all pixels that contain finite values
  511 + void mask_finite(unsigned char* mask, bool PROGRESS = false){
  512 + if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
  513 + if(header.data_type ==envi_header::float32)
  514 + ((bsq<float>*)file)->mask_finite(mask, PROGRESS);
  515 + else if(header.data_type == envi_header::float64)
  516 + ((bsq<double>*)file)->mask_finite(mask, PROGRESS);
  517 + else
  518 + std::cout<<"ERROR: unidentified data type"<<std::endl;
  519 + }
  520 +
  521 + else if(header.interleave == envi_header::BIL){ //if the infile is bil file
  522 + if(header.data_type ==envi_header::float32)
  523 + ((bil<float>*)file)->mask_finite(mask, PROGRESS);
  524 + else if(header.data_type == envi_header::float64)
  525 + ((bil<double>*)file)->mask_finite(mask, PROGRESS);
  526 + else
  527 + std::cout<<"ERROR: unidentified data type"<<std::endl;
  528 + }
  529 +
  530 + else if(header.interleave == envi_header::BIP){ //if the infile is bip file
  531 + if(header.data_type ==envi_header::float32)
  532 + ((bip<float>*)file)->mask_finite(mask, PROGRESS);
  533 + else if(header.data_type == envi_header::float64)
  534 + ((bip<double>*)file)->mask_finite(mask, PROGRESS);
  535 + else
  536 + std::cout<<"ERROR: unidentified data type"<<std::endl;
  537 + }
  538 + }
  539 +
510 /// Applies a mask to the ENVI file. 540 /// Applies a mask to the ENVI file.
511 541
512 /// @param outfile is the name of the resulting masked output file 542 /// @param outfile is the name of the resulting masked output file
@@ -560,17 +590,31 @@ public: @@ -560,17 +590,31 @@ public:
560 return ((bsq<float>*)file)->sift((float*)matrix, p); 590 return ((bsq<float>*)file)->sift((float*)matrix, p);
561 else if (header.data_type == envi_header::float64) 591 else if (header.data_type == envi_header::float64)
562 return ((bsq<double>*)file)->sift((double*)matrix, p); 592 return ((bsq<double>*)file)->sift((double*)matrix, p);
563 - else 593 + else{
564 std::cout << "ERROR: unidentified data type" << std::endl; 594 std::cout << "ERROR: unidentified data type" << std::endl;
  595 + exit(1);
  596 + }
565 } 597 }
566 598
567 if (header.interleave == envi_header::BIP){ 599 if (header.interleave == envi_header::BIP){
568 - std::cout<<"Memory sifting not supported for BIP files"<<std::endl;  
569 - exit(1); 600 + if (header.data_type == envi_header::float32)
  601 + return ((bip<float>*)file)->sift((float*)matrix, p);
  602 + else if (header.data_type == envi_header::float64)
  603 + return ((bip<double>*)file)->sift((double*)matrix, p);
  604 + else{
  605 + std::cout << "ERROR: unidentified data type" << std::endl;
  606 + exit(1);
  607 + }
570 } 608 }
571 if (header.interleave == envi_header::BIL){ 609 if (header.interleave == envi_header::BIL){
572 - std::cout<<"Memory sifting not supported for BIL files"<<std::endl;  
573 - exit(1); 610 + if (header.data_type == envi_header::float32)
  611 + return ((bil<float>*)file)->sift((float*)matrix, p);
  612 + else if (header.data_type == envi_header::float64)
  613 + return ((bil<double>*)file)->sift((double*)matrix, p);
  614 + else{
  615 + std::cout << "ERROR: unidentified data type" << std::endl;
  616 + exit(1);
  617 + }
574 } 618 }
575 return false; 619 return false;
576 620
@@ -684,30 +728,30 @@ public: @@ -684,30 +728,30 @@ public:
684 /// @param rb2 is the label value for the right baseline point for the second peak (denominator) 728 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
685 /// @param pos2 is the label value for the second peak (denominator) position 729 /// @param pos2 is the label value for the second peak (denominator) position
686 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 730 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
687 - bool ph_to_ph(double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, void * result){ 731 + bool ph_to_ph(void * result, double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, unsigned char* mask){
688 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 732 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
689 if(header.data_type ==envi_header::float32) 733 if(header.data_type ==envi_header::float32)
690 - return ((bsq<float>*)file)->ph_to_ph(lb1, rb1, pos1, lb2, rb2, pos2, (float*)result); 734 + return ((bsq<float>*)file)->ph_to_ph((float*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask);
691 else if(header.data_type == envi_header::float64) 735 else if(header.data_type == envi_header::float64)
692 - return ((bsq<double>*)file)->ph_to_ph(lb1, rb1, pos1, lb2, rb2, pos2, (double*)result); 736 + return ((bsq<double>*)file)->ph_to_ph((double*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask);
693 else 737 else
694 std::cout<<"ERROR: unidentified data type"<<std::endl; 738 std::cout<<"ERROR: unidentified data type"<<std::endl;
695 } 739 }
696 740
697 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 741 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
698 if(header.data_type ==envi_header::float32) 742 if(header.data_type ==envi_header::float32)
699 - return ((bil<float>*)file)->ph_to_ph(lb1, rb1, pos1, lb2, rb2, pos2, (float*)result); 743 + return ((bil<float>*)file)->ph_to_ph((float*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask);
700 else if(header.data_type == envi_header::float64) 744 else if(header.data_type == envi_header::float64)
701 - return ((bil<double>*)file)->ph_to_ph(lb1, rb1, pos1, lb2, rb2, pos2, (double*)result); 745 + return ((bil<double>*)file)->ph_to_ph((double*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask);
702 else 746 else
703 std::cout<<"ERROR: unidentified data type"<<std::endl; 747 std::cout<<"ERROR: unidentified data type"<<std::endl;
704 } 748 }
705 749
706 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 750 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
707 if(header.data_type ==envi_header::float32) 751 if(header.data_type ==envi_header::float32)
708 - return ((bip<float>*)file)->ph_to_ph(lb1, rb1, pos1, lb2, rb2, pos2, (float*)result); 752 + return ((bip<float>*)file)->ph_to_ph((float*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask);
709 else if(header.data_type == envi_header::float64) 753 else if(header.data_type == envi_header::float64)
710 - return ((bip<double>*)file)->ph_to_ph(lb1, rb1, pos1, lb2, rb2, pos2, (double*)result); 754 + return ((bip<double>*)file)->ph_to_ph((double*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask);
711 else 755 else
712 std::cout<<"ERROR: unidentified data type"<<std::endl; 756 std::cout<<"ERROR: unidentified data type"<<std::endl;
713 } 757 }
@@ -728,30 +772,30 @@ public: @@ -728,30 +772,30 @@ public:
728 /// @param rb2 is the label value for the right baseline point for the second peak (denominator) 772 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
729 /// @param pos2 is the label value for the second peak (denominator) position 773 /// @param pos2 is the label value for the second peak (denominator) position
730 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 774 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
731 - bool pa_to_ph(double lb1, double rb1, double lab1, double rab1, double lb2, double rb2, double pos, void * result){ 775 + bool pa_to_ph(void* result, double lb1, double rb1, double lab1, double rab1, double lb2, double rb2, double pos, unsigned char* mask = NULL){
732 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 776 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
733 if(header.data_type ==envi_header::float32) 777 if(header.data_type ==envi_header::float32)
734 - return ((bsq<float>*)file)->pa_to_ph(lb1, rb1, lab1, rab1, lb2, rb2, pos, (float*)result); 778 + return ((bsq<float>*)file)->pa_to_ph((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask);
735 else if(header.data_type == envi_header::float64) 779 else if(header.data_type == envi_header::float64)
736 - return ((bsq<double>*)file)->pa_to_ph(lb1, rb1, lab1, rab1, lb2, rb2, pos, (double*)result); 780 + return ((bsq<double>*)file)->pa_to_ph((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask);
737 else 781 else
738 std::cout<<"ERROR: unidentified data type"<<std::endl; 782 std::cout<<"ERROR: unidentified data type"<<std::endl;
739 } 783 }
740 784
741 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 785 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
742 if(header.data_type ==envi_header::float32) 786 if(header.data_type ==envi_header::float32)
743 - return ((bil<float>*)file)->pa_to_ph(lb1, rb1, lab1, rab1, lb2, rb2, pos, (float*)result); 787 + return ((bil<float>*)file)->pa_to_ph((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask);
744 else if(header.data_type == envi_header::float64) 788 else if(header.data_type == envi_header::float64)
745 - return ((bil<double>*)file)->pa_to_ph(lb1, rb1, lab1, rab1, lb2, rb2, pos, (double*)result); 789 + return ((bil<double>*)file)->pa_to_ph((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask);
746 else 790 else
747 std::cout<<"ERROR: unidentified data type"<<std::endl; 791 std::cout<<"ERROR: unidentified data type"<<std::endl;
748 } 792 }
749 793
750 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 794 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
751 if(header.data_type ==envi_header::float32) 795 if(header.data_type ==envi_header::float32)
752 - return ((bip<float>*)file)->pa_to_ph(lb1, rb1, lab1, rab1, lb2, rb2, pos, (float*)result); 796 + return ((bip<float>*)file)->pa_to_ph((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask);
753 else if(header.data_type == envi_header::float64) 797 else if(header.data_type == envi_header::float64)
754 - return ((bip<double>*)file)->pa_to_ph(lb1, rb1, lab1, rab1, lb2, rb2, pos, (double*)result); 798 + return ((bip<double>*)file)->pa_to_ph((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask);
755 else 799 else
756 std::cout<<"ERROR: unidentified data type"<<std::endl; 800 std::cout<<"ERROR: unidentified data type"<<std::endl;
757 } 801 }
@@ -774,31 +818,31 @@ public: @@ -774,31 +818,31 @@ public:
774 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator) 818 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
775 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator) 819 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
776 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 820 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
777 - bool pa_to_pa(double lb1, double rb1, double lab1, double rab1,  
778 - double lb2, double rb2, double lab2, double rab2, void* result){ 821 + bool pa_to_pa(void* result, double lb1, double rb1, double lab1, double rab1,
  822 + double lb2, double rb2, double lab2, double rab2, unsigned char* mask = NULL){
779 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 823 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
780 if(header.data_type ==envi_header::float32) 824 if(header.data_type ==envi_header::float32)
781 - return ((bsq<float>*)file)->pa_to_pa(lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, (float*)result); 825 + return ((bsq<float>*)file)->pa_to_pa((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask);
782 else if(header.data_type == envi_header::float64) 826 else if(header.data_type == envi_header::float64)
783 - return ((bsq<double>*)file)->pa_to_pa(lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, (double*)result); 827 + return ((bsq<double>*)file)->pa_to_pa((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask);
784 else 828 else
785 std::cout<<"ERROR: unidentified data type"<<std::endl; 829 std::cout<<"ERROR: unidentified data type"<<std::endl;
786 } 830 }
787 831
788 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 832 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
789 if(header.data_type ==envi_header::float32) 833 if(header.data_type ==envi_header::float32)
790 - return ((bil<float>*)file)->pa_to_pa(lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, (float*)result); 834 + return ((bil<float>*)file)->pa_to_pa((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask);
791 else if(header.data_type == envi_header::float64) 835 else if(header.data_type == envi_header::float64)
792 - return ((bil<double>*)file)->pa_to_pa(lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, (double*)result); 836 + return ((bil<double>*)file)->pa_to_pa((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask);
793 else 837 else
794 std::cout<<"ERROR: unidentified data type"<<std::endl; 838 std::cout<<"ERROR: unidentified data type"<<std::endl;
795 } 839 }
796 840
797 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 841 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
798 if(header.data_type ==envi_header::float32) 842 if(header.data_type ==envi_header::float32)
799 - return ((bip<float>*)file)->pa_to_pa(lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, (float*)result); 843 + return ((bip<float>*)file)->pa_to_pa((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask);
800 else if(header.data_type == envi_header::float64) 844 else if(header.data_type == envi_header::float64)
801 - return ((bip<double>*)file)->pa_to_pa(lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, (double*)result); 845 + return ((bip<double>*)file)->pa_to_pa((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask);
802 else 846 else
803 std::cout<<"ERROR: unidentified data type"<<std::endl; 847 std::cout<<"ERROR: unidentified data type"<<std::endl;
804 } 848 }
@@ -817,30 +861,30 @@ public: @@ -817,30 +861,30 @@ public:
817 /// @param lab is the label for the start of the peak 861 /// @param lab is the label for the start of the peak
818 /// @param rab is the label for the end of the peak 862 /// @param rab is the label for the end of the peak
819 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size 863 /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size
820 - bool cpoint(double lb1, double rb1, double lab1, double rab1, void* result){ 864 + bool centroid(void* result, double lb1, double rb1, double lab1, double rab1, unsigned char* mask = NULL){
821 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file 865 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
822 if(header.data_type ==envi_header::float32) 866 if(header.data_type ==envi_header::float32)
823 - return ((bsq<float>*)file)->cpoint(lb1, rb1, lab1, rab1, (float*)result); 867 + return ((bsq<float>*)file)->centroid((float*)result, lb1, rb1, lab1, rab1, mask);
824 else if(header.data_type == envi_header::float64) 868 else if(header.data_type == envi_header::float64)
825 - return ((bsq<double>*)file)->cpoint(lb1, rb1, lab1, rab1, (double*)result); 869 + return ((bsq<double>*)file)->centroid((double*)result, lb1, rb1, lab1, rab1, mask);
826 else 870 else
827 std::cout<<"ERROR: unidentified data type"<<std::endl; 871 std::cout<<"ERROR: unidentified data type"<<std::endl;
828 } 872 }
829 873
830 else if(header.interleave == envi_header::BIL){ //if the infile is bil file 874 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
831 if(header.data_type ==envi_header::float32) 875 if(header.data_type ==envi_header::float32)
832 - return ((bil<float>*)file)->cpoint(lb1, rb1, lab1, rab1, (float*)result); 876 + return ((bil<float>*)file)->centroid((float*)result, lb1, rb1, lab1, rab1, mask);
833 else if(header.data_type == envi_header::float64) 877 else if(header.data_type == envi_header::float64)
834 - return ((bil<double>*)file)->cpoint(lb1, rb1, lab1, rab1, (double*)result); 878 + return ((bil<double>*)file)->centroid((double*)result, lb1, rb1, lab1, rab1, mask);
835 else 879 else
836 std::cout<<"ERROR: unidentified data type"<<std::endl; 880 std::cout<<"ERROR: unidentified data type"<<std::endl;
837 } 881 }
838 882
839 else if(header.interleave == envi_header::BIP){ //if the infile is bip file 883 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
840 if(header.data_type ==envi_header::float32) 884 if(header.data_type ==envi_header::float32)
841 - return ((bip<float>*)file)->cpoint(lb1, rb1, lab1, rab1,(float*)result); 885 + return ((bip<float>*)file)->centroid((float*)result, lb1, rb1, lab1, rab1, mask);
842 else if(header.data_type == envi_header::float64) 886 else if(header.data_type == envi_header::float64)
843 - return ((bip<double>*)file)->cpoint(lb1, rb1, lab1, rab1, (double*)result); 887 + return ((bip<double>*)file)->centroid((double*)result, lb1, rb1, lab1, rab1, mask);
844 else 888 else
845 std::cout<<"ERROR: unidentified data type"<<std::endl; 889 std::cout<<"ERROR: unidentified data type"<<std::endl;
846 } 890 }
@@ -6,6 +6,12 @@ @@ -6,6 +6,12 @@
6 #include <cstring> 6 #include <cstring>
7 #include <utility> 7 #include <utility>
8 8
  9 +#ifdef _WIN32
  10 + #include <float.h>
  11 +#else
  12 + #include<cmath>
  13 +#endif
  14 +
9 namespace stim{ 15 namespace stim{
10 16
11 /** 17 /**
@@ -113,6 +119,46 @@ protected: @@ -113,6 +119,46 @@ protected:
113 119
114 return c[2] * R[0] * R[1] + c[1] * R[0] + c[0]; //calculate and return the index (trust me this works) 120 return c[2] * R[0] * R[1] + c[1] * R[0] + c[0]; //calculate and return the index (trust me this works)
115 } 121 }
  122 +
  123 + /// Returns the 3D coordinates of a specified index
  124 + void xyb(size_t idx, size_t& x, size_t& y, size_t& b){
  125 +
  126 + size_t c[3];
  127 +
  128 + c[2] = idx / (R[0] * R[1]);
  129 + c[1] = (idx - c[2] * R[0] * R[1]) / R[0];
  130 + c[0] = idx - c[2] * R[0] * R[1] - c[1] * R[0];
  131 +
  132 + x = c[O[0]];
  133 + y = c[O[1]];
  134 + b = c[O[2]];
  135 + }
  136 +
  137 +public:
  138 + /// Get a mask that has all pixels with inf or NaN values masked out (false)
  139 + void mask_finite(unsigned char* mask, bool PROGRESS = false){
  140 + size_t XY = X() * Y();
  141 + memset(mask, 255, XY * sizeof(unsigned char)); //initialize the mask to zero (0)
  142 + T* page = (T*)malloc(R[0] * R[1] * sizeof(T)); //allocate space for a page of data
  143 +
  144 + for(size_t p = 0; p < R[2]; p++){ //for each page
  145 + binary<T>::read_page(page, p); //read a page
  146 + for(size_t i = 0; i < R[0] * R[1]; i++){ //for each pixel in that page
  147 +
  148 +#ifdef _WIN32
  149 + if(!_finite(page[i])){ //if the value at index i is finite
  150 +#else
  151 + if(!std::isfinite(page[i])){ //C++11 implementation
  152 +#endif
  153 + size_t x, y, b;
  154 + xyb(p * R[0] * R[1] + i, x, y, b); //find the 3D coordinates of the value
  155 + mask[ y * X() + x ] = 0; //mask the pixel (it's not bad)
  156 + }
  157 + }
  158 + if(PROGRESS) progress = (double)(p + 1) / (double)R[2] * 100;
  159 + }
  160 + }
  161 +
116 }; 162 };
117 163
118 } //end namespace STIM 164 } //end namespace STIM
stim/parser/arguments.h
@@ -97,7 +97,7 @@ namespace stim{ @@ -97,7 +97,7 @@ namespace stim{
97 } 97 }
98 98
99 //return the value of a floating point option 99 //return the value of a floating point option
100 - float as_float(size_t n = 0) 100 + double as_float(size_t n = 0)
101 { 101 {
102 if(!flag) 102 if(!flag)
103 { 103 {