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

stim/envi/bil.h
... ... @@ -600,7 +600,7 @@ public:
600 600 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
601 601 /// @param pos2 is the label value for the second peak (denominator) position
602 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 605 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
606 606 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
... ... @@ -630,8 +630,8 @@ public:
630 630 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
631 631 /// @param pos2 is the label value for the second peak (denominator) position
632 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 636 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
637 637 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
... ... @@ -663,8 +663,8 @@ public:
663 663 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
664 664 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
665 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 669 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
670 670 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
... ... @@ -773,7 +773,7 @@ public:
773 773 /// @param lab is the label for the start of the peak
774 774 /// @param rab is the label for the end of the peak
775 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 777 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
778 778 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
779 779  
... ... @@ -782,9 +782,7 @@ public:
782 782 area(lb, rb, lab, rab, p2);
783 783 //calculate the ratio in result
784 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 786 result[i] = p1[i] / p2[i];
789 787 }
790 788  
... ... @@ -800,16 +798,16 @@ public:
800 798 /// @param mask_band is the band used to specify the mask
801 799 /// @param threshold is the threshold used to determine if the mask value is true or false
802 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 803 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
806 804 band(temp, mask_band, PROGRESS);
807 805  
808 806 for (unsigned long long i = 0; i < X() * Y(); i++) {
809 807 if (temp[i] < threshold)
810   - p[i] = 0;
  808 + mask[i] = 0;
811 809 else
812   - p[i] = 255;
  810 + mask[i] = 255;
813 811 }
814 812  
815 813 free(temp);
... ... @@ -850,6 +848,36 @@ public:
850 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 881 /// Saves to disk only those spectra corresponding to mask values != 0
854 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 883 bool sift(std::string outfile, unsigned char* p, bool PROGRESS = false){
... ...
stim/envi/bip.h
... ... @@ -526,7 +526,7 @@ public:
526 526 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
527 527 /// @param pos2 is the label value for the second peak (denominator) position
528 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 531 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
532 532 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
... ... @@ -556,8 +556,8 @@ public:
556 556 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
557 557 /// @param pos2 is the label value for the second peak (denominator) position
558 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 562 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
563 563 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
... ... @@ -589,8 +589,8 @@ public:
589 589 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
590 590 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
591 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 595 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
596 596 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
... ... @@ -699,7 +699,7 @@ public:
699 699 /// @param lab is the label for the start of the peak
700 700 /// @param rab is the label for the end of the peak
701 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 703 T* p1 = (T*)malloc(X() * Y() * sizeof(T));
704 704 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
705 705  
... ... @@ -708,9 +708,7 @@ public:
708 708 area(lb, rb, lab, rab, p2);
709 709 //calculate the ratio in result
710 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 712 result[i] = p1[i] / p2[i];
715 713 }
716 714  
... ... @@ -726,16 +724,16 @@ public:
726 724 /// @param mask_band is the band used to specify the mask
727 725 /// @param threshold is the threshold used to determine if the mask value is true or false
728 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 729 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
732 730 band(temp, mask_band, PROGRESS);
733 731  
734 732 for (unsigned long long i = 0; i < X() * Y();i++) {
735 733 if (temp[i] < threshold)
736   - p[i] = 0;
  734 + mask[i] = 0;
737 735 else
738   - p[i] = 255;
  736 + mask[i] = 255;
739 737 }
740 738  
741 739 free(temp);
... ... @@ -776,6 +774,33 @@ public:
776 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 805 /// Saves to disk only those spectra corresponding to mask values != 0
781 806 bool sift(std::string outfile, unsigned char* mask, bool PROGRESS = false){
... ...
stim/envi/bsq.h
... ... @@ -436,9 +436,7 @@ public:
436 436 cur = (T*) malloc(S);
437 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 440 unsigned long long n = w.size();
443 441 unsigned long long ai = 0; //left bound position
444 442 unsigned long long bi = n - 1; //right bound position
... ... @@ -450,26 +448,30 @@ public:
450 448 std::cout<<"ERROR: left bound or right bound out of bandwidth"<<std::endl;
451 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 452 else if(lb > rb){
455 453 std::cout<<"ERROR: right bound should be bigger than left bound"<<std::endl;
456 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 459 ai++;
462 460 }
463 461 while (rab <= w[bi]){
464 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 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 475 for(unsigned long long j = 0; j < XY; j++){
474 476 result[j] += (T)((rab - w[bi]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
475 477 }
... ... @@ -479,13 +481,12 @@ public:
479 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 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 490 result[j] += (T)((w[ai] - w[ai-1]) * ((double)cur[j] + (double)cur2[j]) / 2.0);
490 491 }
491 492 std::swap(cur,cur2); //swap the band pointers
... ... @@ -507,20 +508,22 @@ public:
507 508 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
508 509 /// @param pos2 is the label value for the second peak (denominator) position
509 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 519 //get the two peak band
516 520 height(lb1, rb1, pos1, p1);
517 521 height(lb2, rb2, pos2, p2);
518 522 //calculate the ratio in result
519 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 525 result[i] = p1[i] / p2[i];
  526 + }
524 527 }
525 528  
526 529 free(p1);
... ... @@ -537,20 +540,20 @@ public:
537 540 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
538 541 /// @param pos2 is the label value for the second peak (denominator) position
539 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 551 //get the area and the peak band
547 552 area(lb1, rb1, lab1, rab1, p1);
548 553 height(lb2, rb2, pos, p2);
549 554 //calculate the ratio in result
550 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 557 result[i] = p1[i] / p2[i];
555 558 }
556 559  
... ... @@ -570,21 +573,21 @@ public:
570 573 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
571 574 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
572 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 584 //get the area and the peak band
580 585 area(lb1, rb1, lab1, rab1, p1);
581 586 area(lb2, rb2, lab2, rab2, p2);
582 587 //calculate the ratio in result
583 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 593 free(p1);
... ... @@ -592,7 +595,7 @@ public:
592 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 600 /// @param lb is the label value for the left baseline point
598 601 /// @param rb is the label value for the right baseline point
... ... @@ -613,8 +616,6 @@ public:
613 616 cur = (T*) malloc(S);
614 617 cur2 = (T*) malloc(S);
615 618  
616   - memset(result, (char)0, S);
617   -
618 619 //find the wavelenght position in the whole band
619 620 unsigned long long n = w.size();
620 621 unsigned long long ai = 0; //left bound position
... ... @@ -642,6 +643,8 @@ public:
642 643 band(lp, lb);
643 644 band(rp, rb);
644 645  
  646 + memset(result, (char)0, S); //initialize the integral to zero (0)
  647 +
645 648 //calculate the beginning and the ending part
646 649 baseline_band(lb, rb, lp, rp, rab, cur2); //ending part
647 650 baseline_band(lb, rb, lp, rp, w[bi], cur);
... ... @@ -656,12 +659,11 @@ public:
656 659  
657 660 //calculate f(x) times x
658 661 ai++;
659   - for(unsigned long long i = ai; i <= bi ;i++)
660   - {
  662 + for(unsigned long long i = ai; i <= bi ;i++){
661 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 668 std::swap(cur,cur2); //swap the band pointers
667 669 }
... ... @@ -674,25 +676,27 @@ public:
674 676 }
675 677  
676 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 681 /// @param lb is the label value for the left baseline point
679 682 /// @param rb is the label value for the right baseline point
680 683 /// @param lab is the label for the start of the peak
681 684 /// @param rab is the label for the end of the peak
682 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 689 T* p2 = (T*)malloc(X() * Y() * sizeof(T));
686 690  
  691 + memset(result, 0, bytes); //initialize the ratio result to zero (0)
687 692 //get the area and the peak band
688 693 x_area(lb, rb, lab, rab, p1);
689 694 area(lb, rb, lab, rab, p2);
690 695 //calculate the ratio in result
691 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 698 result[i] = p1[i] / p2[i];
  699 + }
696 700 }
697 701  
698 702 free(p1);
... ... @@ -707,16 +711,16 @@ public:
707 711 /// @param mask_band is the band used to specify the mask
708 712 /// @param threshold is the threshold used to determine if the mask value is true or false
709 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 716 T* temp = (T*)malloc(X() * Y() * sizeof(T)); //allocate memory for the certain band
713 717 band(temp, mask_band);
714 718  
715 719 for (unsigned long long i = 0; i < X() * Y(); i++) {
716 720 if (temp[i] < threshold)
717   - p[i] = 0;
  721 + mask[i] = 0;
718 722 else
719   - p[i] = 255;
  723 + mask[i] = 255;
720 724  
721 725 if(PROGRESS) progress = (double) (i+1) / (X() * Y()) * 100;
722 726 }
... ...
stim/envi/envi.h
... ... @@ -475,31 +475,31 @@ public:
475 475 /// @param mask_band is the label for the band that will be used to build the mask
476 476 /// @param threshold is a value selected such that all band values greater than threshold will have a mask value of 'true'
477 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 480 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
481 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 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 485 else
486 486 std::cout<<"ERROR: unidentified data type"<<std::endl;
487 487 }
488 488  
489 489 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
490 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 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 494 else
495 495 std::cout<<"ERROR: unidentified data type"<<std::endl;
496 496 }
497 497  
498 498 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
499 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 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 503 else
504 504 std::cout<<"ERROR: unidentified data type"<<std::endl;
505 505 }
... ... @@ -507,6 +507,36 @@ public:
507 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 540 /// Applies a mask to the ENVI file.
511 541  
512 542 /// @param outfile is the name of the resulting masked output file
... ... @@ -560,17 +590,31 @@ public:
560 590 return ((bsq<float>*)file)->sift((float*)matrix, p);
561 591 else if (header.data_type == envi_header::float64)
562 592 return ((bsq<double>*)file)->sift((double*)matrix, p);
563   - else
  593 + else{
564 594 std::cout << "ERROR: unidentified data type" << std::endl;
  595 + exit(1);
  596 + }
565 597 }
566 598  
567 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 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 619 return false;
576 620  
... ... @@ -684,30 +728,30 @@ public:
684 728 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
685 729 /// @param pos2 is the label value for the second peak (denominator) position
686 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 732 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
689 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 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 737 else
694 738 std::cout<<"ERROR: unidentified data type"<<std::endl;
695 739 }
696 740  
697 741 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
698 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 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 746 else
703 747 std::cout<<"ERROR: unidentified data type"<<std::endl;
704 748 }
705 749  
706 750 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
707 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 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 755 else
712 756 std::cout<<"ERROR: unidentified data type"<<std::endl;
713 757 }
... ... @@ -728,30 +772,30 @@ public:
728 772 /// @param rb2 is the label value for the right baseline point for the second peak (denominator)
729 773 /// @param pos2 is the label value for the second peak (denominator) position
730 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 776 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
733 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 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 781 else
738 782 std::cout<<"ERROR: unidentified data type"<<std::endl;
739 783 }
740 784  
741 785 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
742 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 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 790 else
747 791 std::cout<<"ERROR: unidentified data type"<<std::endl;
748 792 }
749 793  
750 794 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
751 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 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 799 else
756 800 std::cout<<"ERROR: unidentified data type"<<std::endl;
757 801 }
... ... @@ -774,31 +818,31 @@ public:
774 818 /// @param lab2 is the label value for the left bound (start of the integration) of the second peak (denominator)
775 819 /// @param rab2 is the label value for the right bound (end of the integration) of the second peak (denominator)
776 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 823 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
780 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 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 828 else
785 829 std::cout<<"ERROR: unidentified data type"<<std::endl;
786 830 }
787 831  
788 832 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
789 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 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 837 else
794 838 std::cout<<"ERROR: unidentified data type"<<std::endl;
795 839 }
796 840  
797 841 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
798 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 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 846 else
803 847 std::cout<<"ERROR: unidentified data type"<<std::endl;
804 848 }
... ... @@ -817,30 +861,30 @@ public:
817 861 /// @param lab is the label for the start of the peak
818 862 /// @param rab is the label for the end of the peak
819 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 865 if(header.interleave == envi_header::BSQ){ //if the infile is bsq file
822 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 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 870 else
827 871 std::cout<<"ERROR: unidentified data type"<<std::endl;
828 872 }
829 873  
830 874 else if(header.interleave == envi_header::BIL){ //if the infile is bil file
831 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 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 879 else
836 880 std::cout<<"ERROR: unidentified data type"<<std::endl;
837 881 }
838 882  
839 883 else if(header.interleave == envi_header::BIP){ //if the infile is bip file
840 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 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 888 else
845 889 std::cout<<"ERROR: unidentified data type"<<std::endl;
846 890 }
... ...
stim/envi/hsi.h
... ... @@ -6,6 +6,12 @@
6 6 #include <cstring>
7 7 #include <utility>
8 8  
  9 +#ifdef _WIN32
  10 + #include <float.h>
  11 +#else
  12 + #include<cmath>
  13 +#endif
  14 +
9 15 namespace stim{
10 16  
11 17 /**
... ... @@ -113,6 +119,46 @@ protected:
113 119  
114 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 164 } //end namespace STIM
... ...
stim/parser/arguments.h
... ... @@ -97,7 +97,7 @@ namespace stim{
97 97 }
98 98  
99 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 102 if(!flag)
103 103 {
... ...