~ubuntu-branches/debian/sid/3depict/sid

« back to all changes in this revision

Viewing changes to src/APTClasses.h

  • Committer: Bazaar Package Importer
  • Author(s): D Haley, Sylvestre Ledru
  • Date: 2011-04-12 17:44:06 UTC
  • mfrom: (1.2.1 upstream) (3.1.2 experimental)
  • Revision ID: james.westby@ubuntu.com-20110412174406-zz06iu3xmardt43s
Tags: 0.0.5-1
[ Sylvestre Ledru ]
* watch file added
* Switch to dpkg-source 3.0 (quilt) format

* New upstream version 

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
#ifndef APTCLASSES_H
20
20
#define APTCLASSES_H
21
 
#include "basics.h"
 
21
//#include "datastructs.h"
22
22
#include "endianTest.h"
23
23
#include "mathfuncs.h"
24
 
#include "common.h"
 
24
#include "commonConstants.h"
 
25
#include "basics.h"
25
26
 
26
27
#include <string>
27
28
#include <iostream>
34
35
#include <fstream>
35
36
#include <new>//std::bad_alloc
36
37
 
 
38
//!Allowable export ion formats
 
39
enum
 
40
{
 
41
        IONFORMAT_POS=1,
 
42
};
37
43
 
38
44
using std::vector;
39
45
 
59
65
        POS_ERR_FINAL // Not actually an error, but tells us where the end of the num is.
60
66
};
61
67
 
62
 
#ifdef __LITTLE_ENDIAN__
63
 
        //swaps bytes
64
 
        void floatSwapBytes(float *inFloat);
65
 
#endif
66
 
 
67
 
#ifdef DEBUG
68
 
        //Dump point in form (x,y,z) to stderr
69
 
        void DumpPoint(const Point3D &pt);
70
 
 
71
 
        //!Make a pos file from a set of points, assigning them a mass of "mass"
72
 
        void makePos(const vector<Point3D> &points, float mass, const char *name);
73
 
#endif
74
68
 
75
69
//!make a pos file from a set of a set of IonHits
76
 
void makePos(const vector<IonHit> &points, const char *name);
 
70
unsigned int IonVectorToPos(const vector<IonHit> &points, const std::string &name);
77
71
 
78
72
//!make/append to a pos file from a set of a set of IonHits
79
73
void appendPos(const vector<IonHit> &points, const char *name);
80
74
 
81
 
//!Print  short summmary of the ions in a list
82
 
void PrintSummary(std::vector<IonHit> &posIons, RangeFile &rangeFile);
83
 
 
84
 
 
85
 
//!Returns the limits of a dataset of Ions
86
 
void dataLimits(const vector<IonHit> &posIons, Point3D &low, Point3D &upper);
87
 
 
88
 
 
89
 
 
90
 
 
91
 
//! Returns the shortest distance between a facet and a Point 
92
 
/* The inputs are the facet points (ABC) and the point P.
93
 
 * distance is shortest using standard plane version 
94
 
 * \f$ D = \vec{AB} \cdot \vec{n} \f$ 
95
 
 * iff dot products to each combination of \f$ \left( AP,BP,CP \right) \leq 0 \f$
96
 
 * otherwise closest point is on the boundary of the simplex.
97
 
 * tested by shortest distance to each line segment (E is shortest pt. AB is line segement)
98
 
 * \f$ \vec{E} = \frac{\vec{AB}}{|\vec{AB}|} 
99
 
 *  ( \vec{PB} \cdot \vec{AB})\f$
100
 
 */
101
 
float distanceToFacet(const Point3D &fA, const Point3D &fB, 
102
 
                        const Point3D &fC, const Point3D &p, const Point3D &normal);
103
 
 
104
 
 
105
 
//! Returns the shortest distance between a line segment and a given point
106
 
/* The inpus are the ends of the line segment and the point. Uses the formula that 
107
 
 * \f$ 
108
 
 * D = \abs{\vec{PE}}\f$
109
 
 * \f[ 
110
 
 * \mathrm{~if~} \vec{PA} \cdot \vec{AB} > 0 
111
 
 * \rightarrow \vec{PE} = \vec{A} 
112
 
 * \f]
113
 
 * \f[
114
 
 * \mathrm{~if~} \vec{AB} \cdot \vec{PB} > 0 ~\&~ \vec{PA} \cdot \vec{AB} < 0
115
 
 * \rightarrow \vec{PB} \cdot \frac{\vec{AB}}{\abs{\vec{AB}}} 
116
 
 * \f]
117
 
 * \f[
118
 
 * \mathrm{~if~} \vec{PB} \cdot \vec{AB} < 0 
119
 
 * \rightarrow \vec{B} 
120
 
 * \f]
121
 
 */
122
 
float distanceToSegment(const Point3D &fA, const Point3D &fB, const Point3D &p);
123
 
 
124
 
 
125
 
//!Check which way vectors attached to two 3D points "point",  - "together", "apart" or "in common"
126
 
// 
127
 
unsigned int vectorPointDir(const Point3D &fA, const Point3D &fB, 
128
 
                                const Point3D &vA, const Point3D &vB);
129
 
 
130
 
 
131
 
void DumpIonInfo(const std::vector<IonHit> &vec, 
132
 
                                std::ostream &strm);
133
 
 
134
 
//!Return the minimum of 2 objects(inline)
135
 
template<class T> inline T min2(T T1, T T2)
136
 
{
137
 
        if(T1 < T2)
138
 
                return T1;
139
 
        else
140
 
                return T2;
141
 
}
142
 
 
143
 
 
144
 
 
145
 
//!Return the minimum of 3 objects (inline)
146
 
template<class T> inline T min3(T T1,T T2,T T3)
147
 
{
148
 
        //check Tor T1 smallest
149
 
        if(T1 < T2 && T1 < T3)
150
 
                return T1;
151
 
 
152
 
        //either T2 or T3 is smallest
153
 
        if(T2 < T3)
154
 
                return T2;
155
 
        else
156
 
                return T3;
157
 
}
 
75
//!Set the bounds from an array of ion hits
 
76
BoundCube getIonDataLimits(const vector<IonHit> &p);//
158
77
 
159
78
//Range file strucutres
160
79
//=========
161
 
//!Data holder for colour as float
162
 
typedef struct RGB
163
 
{
164
 
        float red;
165
 
        float green;
166
 
        float blue;
167
 
} RGB;
168
80
 
169
81
enum{ RANGE_ERR_OPEN =1, 
170
82
        RANGE_ERR_FORMAT,
185
97
 
186
98
//Pos file structure
187
99
//===========
188
 
//!Record as stored in a .POS file
189
 
typedef struct IONHIT
190
 
{
191
 
        float pos[3];
192
 
        float massToCharge;
193
 
} IONHIT;
194
100
//=========
195
101
 
196
 
enum PointDir{  POINTDIR_TOGETHER =0,
197
 
                POINTDIR_IN_COMMON,
198
 
                POINTDIR_APART
199
 
             };
200
 
             
201
 
//!Create an pos file from a vector of IonHits
202
 
unsigned int IonVectorToPos(const std::vector<IonHit> &ionVec, 
203
 
                                        const std::string &filename);
204
 
             
205
 
//!Create a "quality"-metric pos file,
206
 
/*! The generated pos file is from  replacing mass to charge with the 
207
 
 * chosen quality tally based  metric ie quality = good_counts/bad_counts. 
208
 
 */
209
 
bool createQualityPos(const std::vector<Point3D> &p, 
210
 
        const std::vector<std::pair<unsigned int, unsigned int> > &q, 
211
 
                                                const std::string &str);
212
 
 
 
102
             
 
103
             
213
104
//!This is a data holding class for POS file ions, from
214
105
/* Pos ions are typically obtained via reconstructed apt detector hits
215
106
 * and are of form (x,y,z mass/charge)
225
116
                IonHit(const IonHit &);
226
117
                IonHit(Point3D p, float massToCharge);
227
118
 
228
 
                void setHit(const IONHIT *hit);
 
119
                void setHit(float *arr) { pos.setValueArr(arr); massToCharge=arr[3];};
229
120
                void setMassToCharge(float newMassToCharge);
230
121
                void setPos(const Point3D &pos);
231
122
                void setPos(float fX, float fY, float fZ)
258
149
                //the second is the full name
259
150
                std::vector<std::pair<std::string,std::string> > ionNames;
260
151
                //This holds the colours for the ions
261
 
                std::vector<RGB> colours;
 
152
                std::vector<RGBf> colours;
262
153
                
263
154
                //This will contains the number of ranges
264
155
                //
285
176
                //!Retrieve the start and end of a given range as a pair(start,end)
286
177
                std::pair<float,float> getRange(unsigned int ) const;
287
178
                //!Retrieve a given colour from the ion ID
288
 
                RGB getColour(unsigned int) const;
 
179
                RGBf getColour(unsigned int) const;
289
180
                //!Set the colour using the ion ID
290
 
                void setColour(unsigned int, const RGB &r);
 
181
                void setColour(unsigned int, const RGBf &r);
291
182
 
292
183
                
293
184
                //!Retrieve the colour from a given ion ID
373
264
 
374
265
                //!Move a range's mass to a new location
375
266
                bool moveRange(unsigned int range, bool limit, float newMass);
 
267
                //!Move both of a range's masses to a new location
 
268
                bool moveBothRanges(unsigned int range, float newLow, float newHigh);
376
269
                
377
270
};
378
271
 
385
278
 * x,y,z,mass/charge. 
386
279
 * */
387
280
//!Load a pos file into a T of IonHits
388
 
template<class T>
389
 
unsigned int GenericLoadFloatFile(int inputnumcols, int outputnumcols, int index[], T &posIons,const char *posFile, unsigned int &progress, bool (*callback)())
390
 
{
391
 
        //buffersize must be a power of two and at least sizeof(IONHIT)
392
 
        const unsigned int NUMROWS=512;
393
 
        const unsigned int BUFFERSIZE=inputnumcols * sizeof(float) * NUMROWS;
394
 
        const unsigned int BUFFERSIZE2=outputnumcols * sizeof(float) * NUMROWS;
395
 
        char *buffer=new char[BUFFERSIZE];
396
 
        char *buffer2=new char[BUFFERSIZE2];
397
 
        
398
 
        if(!buffer)
399
 
                return POS_ALLOC_FAIL;
400
 
        
401
 
        //open pos file
402
 
        std::ifstream CFile(posFile,std::ios::binary);
403
 
        
404
 
        if(!CFile)
405
 
        {
406
 
                delete[] buffer;
407
 
                delete[] buffer2;
408
 
                return POS_OPEN_FAIL;
409
 
        }
410
 
        
411
 
        CFile.seekg(0,std::ios::end);
412
 
        size_t fileSize=CFile.tellg();
413
 
        
414
 
        if(!fileSize)
415
 
        {
416
 
                delete[] buffer;
417
 
                delete[] buffer2;
418
 
                return POS_EMPTY_FAIL;
419
 
        }
420
 
        
421
 
        CFile.seekg(0,std::ios::beg);
422
 
        
423
 
        //calculate the number of points stored in the POS file
424
 
        IonHit hit;
425
 
        IONHIT *hitStruct;
426
 
        size_t pointCount=0;
427
 
        //regular case
428
 
        size_t curBufferSize=BUFFERSIZE;
429
 
        size_t curBufferSize2=BUFFERSIZE2;
430
 
        
431
 
        if(fileSize % (inputnumcols * sizeof(float)))
432
 
        {
433
 
                delete[] buffer;
434
 
                delete[] buffer2;
435
 
                return POS_SIZE_MODULUS_ERR;    
436
 
        }
437
 
        
438
 
        try
439
 
        {
440
 
                posIons.resize(fileSize/sizeof(IONHIT));
441
 
        }
442
 
        catch(std::bad_alloc)
443
 
        {
444
 
                delete[] buffer;
445
 
                delete[] buffer2;
446
 
                return POS_ALLOC_FAIL;
447
 
        }
448
 
        
449
 
        
450
 
        while(fileSize < curBufferSize) {
451
 
                curBufferSize = curBufferSize >> 1;
452
 
                curBufferSize2 = curBufferSize2 >> 1;
453
 
        }               
454
 
        
455
 
        //Technically this is dependant upon the buffer size.
456
 
        unsigned int curProg = 10000;   
457
 
        size_t ionP=0;
458
 
        int maxCols = inputnumcols * sizeof(float);
459
 
        int maxPosCols = outputnumcols * sizeof(float);
460
 
        do
461
 
        {
462
 
                while((size_t)CFile.tellg() <= fileSize-curBufferSize)
463
 
                {
464
 
                        CFile.read(buffer,curBufferSize);
465
 
                        if(!CFile.good())
466
 
                        {
467
 
                                delete[] buffer;
468
 
                                delete[] buffer2;
469
 
                                return POS_READ_FAIL;
470
 
                        }
471
 
                        
472
 
                        for (int j = 0; j < NUMROWS; j++) // iterate through rows
473
 
                        {
474
 
                                for (int i = 0; i < outputnumcols; i++) // iterate through floats
475
 
                                {
476
 
                                        memcpy(&(buffer2[j * maxPosCols + i * sizeof(float)]), 
477
 
                                                &(buffer[j * maxCols + index[i] * sizeof(float)]), sizeof(float));
478
 
                                }
479
 
                        }
480
 
                        
481
 
                        hitStruct = (IONHIT *)buffer2; 
482
 
                        unsigned int ui;
483
 
                        for(ui=0; ui<curBufferSize2; ui+=(sizeof(IONHIT)))
484
 
                        {
485
 
                                hit.setHit(hitStruct);
486
 
                                //Data bytes stored in pos files are big
487
 
                                //endian. flip as required
488
 
                                #ifdef __LITTLE_ENDIAN__
489
 
                                        hit.switchEndian();     
490
 
                                #endif
491
 
                                
492
 
                                if(hit.hasNaN())
493
 
                                {
494
 
                                        delete[] buffer;
495
 
                                        delete[] buffer2;
496
 
                                        return POS_NAN_LOAD_ERROR;      
497
 
                                }
498
 
                                posIons[ionP] = hit;
499
 
                                ionP++;
500
 
                                
501
 
                                pointCount++;
502
 
                                hitStruct++;
503
 
                        }       
504
 
                        
505
 
                        if(!curProg--)
506
 
                        {
507
 
                                progress= (unsigned int)((float)(CFile.tellg())/((float)fileSize)*100.0f);
508
 
                                curProg=PROGRESS_REDUCE;
509
 
                                if(!(*callback)())
510
 
                                {
511
 
                                        delete[] buffer;
512
 
                                        delete[] buffer2;
513
 
                                        posIons.clear();
514
 
                                        return POS_ABORT_FAIL;
515
 
                                
516
 
                                }
517
 
                        }
518
 
                                
519
 
                }
520
 
 
521
 
                curBufferSize = curBufferSize >> 1 ;
522
 
                curBufferSize2 = curBufferSize2 >> 1 ;
523
 
        }while(curBufferSize2 >= sizeof(IONHIT));
524
 
        
525
 
        ASSERT((unsigned int)CFile.tellg() == fileSize);
526
 
        delete[] buffer;
527
 
        delete[] buffer2;
528
 
        
529
 
        return 0;
530
 
}
531
 
 
532
 
 
533
 
template<class T>
534
 
unsigned int LimitLoadPosFile(int inputnumcols, int outputnumcols, int index[], T &posIons,const char *posFile, size_t limitCount,
535
 
                unsigned int &progress, bool (*callback)())
536
 
{
537
 
        //buffersize must be a power of two and at least sizeof(IONHIT)
538
 
        const unsigned int NUMROWS=1;
539
 
        const unsigned int BUFFERSIZE=inputnumcols * sizeof(float) * NUMROWS;
540
 
        const unsigned int BUFFERSIZE2=outputnumcols * sizeof(float) * NUMROWS;
541
 
        char *buffer=new char[BUFFERSIZE];
542
 
        char *buffer2=new char[BUFFERSIZE2];
543
 
        
544
 
        if(!buffer)
545
 
                return POS_ALLOC_FAIL;
546
 
 
547
 
        //open pos file
548
 
        std::ifstream CFile(posFile,std::ios::binary);
549
 
 
550
 
        if(!CFile)
551
 
        {
552
 
                delete[] buffer;
553
 
                delete[] buffer2;
554
 
                return POS_OPEN_FAIL;
555
 
        }
556
 
        
557
 
        CFile.seekg(0,std::ios::end);
558
 
        size_t fileSize=CFile.tellg();
559
 
 
560
 
        if(!fileSize)
561
 
        {
562
 
                delete[] buffer;
563
 
                delete[] buffer2;
564
 
                return POS_EMPTY_FAIL;
565
 
        }
566
 
        
567
 
        CFile.seekg(0,std::ios::beg);
568
 
        
569
 
        //calculate the number of points stored in the POS file
570
 
        size_t pointCount=0;
571
 
        size_t maxIons;
572
 
        size_t maxCols = inputnumcols * sizeof(float);
573
 
        //regular case
574
 
        
575
 
        if(fileSize % maxCols)
576
 
        {
577
 
                delete[] buffer;
578
 
                delete[] buffer2;
579
 
                return POS_SIZE_MODULUS_ERR;    
580
 
        }
581
 
 
582
 
        maxIons =fileSize/maxCols;
583
 
        limitCount=std::min(limitCount,maxIons);
584
 
 
585
 
        //If we are going to load the whole file, don't use a sampling method to do it.
586
 
        if(limitCount == maxIons)
587
 
        {
588
 
                //Close the file
589
 
                CFile.close();
590
 
                delete[] buffer;
591
 
                delete[] buffer2;
592
 
                //Try opening it using the normal functions
593
 
                return GenericLoadFloatFile(inputnumcols, outputnumcols, index, posIons,posFile,progress, callback);
594
 
        }
595
 
 
596
 
        //Use a sampling method to load the pos file
597
 
        std::vector<size_t> ionsToLoad;
598
 
        try
599
 
        {
600
 
                posIons.resize(limitCount);
601
 
 
602
 
                RandNumGen rng;
603
 
                rng.initTimer();
604
 
                unsigned int dummy;
605
 
                randomDigitSelection(ionsToLoad,maxIons,rng,
606
 
                                limitCount,dummy,callback);
607
 
        }
608
 
        catch(std::bad_alloc)
609
 
        {
610
 
                delete[] buffer;
611
 
                delete[] buffer2;
612
 
                return POS_ALLOC_FAIL;
613
 
        }
614
 
 
615
 
 
616
 
        //sort again    
617
 
        GreaterWithCallback<size_t> g(callback,PROGRESS_REDUCE);
618
 
        std::sort(ionsToLoad.begin(),ionsToLoad.end(),g);
619
 
 
620
 
        unsigned int curProg = PROGRESS_REDUCE; 
621
 
 
622
 
        //TODO: probably not very nice to the disk drive. would be better to
623
 
        //scan ahead for contigous data regions, and load that where possible.
624
 
        //Or switch between different algorithms based upon ionsToLoad.size()/  
625
 
        IONHIT hit;
626
 
        std::ios::pos_type  nextIonPos;
627
 
        for(size_t ui=0;ui<ionsToLoad.size(); ui++)
628
 
        {
629
 
                nextIonPos =  ionsToLoad[ui]*maxCols;
630
 
                
631
 
                if(CFile.tellg() !=nextIonPos )
632
 
                        CFile.seekg(nextIonPos);
633
 
 
634
 
                CFile.read(buffer,BUFFERSIZE);
635
 
 
636
 
                for (int i = 0; i < outputnumcols; i++) // iterate through floats
637
 
                        memcpy(&(buffer2[i * sizeof(float)]), &(buffer[index[i] * sizeof(float)]), sizeof(float));
638
 
                
639
 
                memcpy((char *)(&hit), buffer2, sizeof(IONHIT));
640
 
                
641
 
                if(!CFile.good())
642
 
                        return POS_READ_FAIL;
643
 
                posIons[ui].setHit(&hit);
644
 
                //Data bytes stored in pos files are big
645
 
                //endian. flip as required
646
 
                #ifdef __LITTLE_ENDIAN__
647
 
                        posIons[ui].switchEndian();     
648
 
                #endif
649
 
                
650
 
                if(posIons[ui].hasNaN())
651
 
                {
652
 
                        delete[] buffer;
653
 
                        delete[] buffer2;
654
 
                        return POS_NAN_LOAD_ERROR;      
655
 
                }
656
 
                        
657
 
                pointCount++;
658
 
                if(!curProg--)
659
 
                {
660
 
 
661
 
                        progress= (unsigned int)((float)(CFile.tellg())/((float)fileSize)*100.0f);
662
 
                        curProg=PROGRESS_REDUCE;
663
 
                        if(!(*callback)())
664
 
                        {
665
 
                                delete[] buffer;
666
 
                                posIons.clear();
667
 
                                return POS_ABORT_FAIL;
668
 
                                
669
 
                        }
670
 
                }
671
 
                                
672
 
        }
673
 
 
674
 
        delete[] buffer;
675
 
        delete[] buffer2;
676
 
        return 0;
677
 
}
678
 
 
679
 
template<class T>
680
 
unsigned int LimitRestrictLoadPosFile(T &posIons,const char *posFile, size_t limitCount,
681
 
               const BoundCube &bound,  unsigned int &progress, bool (*callback)())
682
 
{
683
 
        //buffersize must be a power of two and at least sizeof(IONHIT)
684
 
        const unsigned int BUFFERSIZE=8192;
685
 
        char *buffer=new char[BUFFERSIZE];
686
 
        
687
 
        if(!buffer)
688
 
                return POS_ALLOC_FAIL;
689
 
 
690
 
        //open pos file
691
 
        std::ifstream CFile(posFile,std::ios::binary);
692
 
 
693
 
        if(!CFile)
694
 
        {
695
 
                delete[] buffer;
696
 
                return POS_OPEN_FAIL;
697
 
        }
698
 
        
699
 
        CFile.seekg(0,std::ios::end);
700
 
        size_t fileSize=CFile.tellg();
701
 
        
702
 
        if(!fileSize)
703
 
        {
704
 
                delete[] buffer;
705
 
                return POS_EMPTY_FAIL;
706
 
        }
707
 
        
708
 
        CFile.seekg(0,std::ios::beg);
709
 
        
710
 
        //calculate the number of points stored in the POS file
711
 
        size_t pointCount=0;
712
 
        size_t maxIons;
713
 
        //regular case
714
 
        
715
 
        if(fileSize % sizeof(IONHIT))
716
 
        {
717
 
                delete[] buffer;
718
 
                return POS_SIZE_MODULUS_ERR;    
719
 
        }
720
 
 
721
 
        maxIons =fileSize/sizeof(IONHIT);
722
 
        limitCount=std::min(limitCount,maxIons);
723
 
 
724
 
        //If we are going to load the whole file, don't use a sampling method to do it.
725
 
        if(limitCount == maxIons)
726
 
        {
727
 
                //Close the file
728
 
                CFile.close();
729
 
                delete[] buffer;
730
 
                //Try opening it using the normal functions
731
 
                int index[4] = {
732
 
                                0, 1, 2, 3
733
 
                                };
734
 
                return GenericLoadFloatFile(4, 4, index, posIons,posFile,progress, callback);
735
 
        }
736
 
 
737
 
        //Use a sampling method to load the pos file
738
 
        try
739
 
        {
740
 
                posIons.resize(limitCount);
741
 
        }
742
 
        catch(std::bad_alloc)
743
 
        {
744
 
                return POS_ALLOC_FAIL;
745
 
        }
746
 
 
747
 
 
748
 
        RandNumGen rng;
749
 
        rng.initTimer();
750
 
        
751
 
        const size_t RECORD_WIDTH=16;
752
 
 
753
 
        //FIXME: If limitCount is near maxIons, this will be 
754
 
        //very inefficient better to remember only the gaps in that case.
755
 
 
756
 
        //OK, this algorithm is a bit tricky. We need to try to load
757
 
        //the limit size, but discard ions that lie outside the 
758
 
        //desired bounding volume. We don't know in advance how many we will get
759
 
        //until we inspect the data, so we have to guess that all of them fit, then
760
 
        //keep trying more until we run out of ions.
761
 
        //
762
 
        //So keep adding new ions, limitCount at a time, checking that the new
763
 
        //indicies are unique in the load.
764
 
        
765
 
        //Random sequence to load for this pass and already loaded sequence respectively
766
 
        std::vector<size_t> ionsToLoad,ionsLoaded;
767
 
        do
768
 
        {
769
 
                //Step 1: Generate random sequence
770
 
                //====
771
 
                
772
 
                //Create an array of random numbers  to load
773
 
                for(size_t ui=0; ui<limitCount; ui++)
774
 
                        ionsToLoad[ui] = (rng.genUniformDev()*(maxIons-1));
775
 
 
776
 
                //Sort & Remove repeated indices 
777
 
                std::sort(ionsToLoad.begin(),ionsToLoad.end());
778
 
                std::unique(ionsToLoad.begin(),ionsToLoad.end());       
779
 
 
780
 
                //Step 2: Remove any entries we have already loaded from the list
781
 
                //===
782
 
                size_t seenCount;
783
 
                seenCount=0;
784
 
                
785
 
                //Sort already loaded ions before doing binary search below
786
 
                std::sort(ionsLoaded.begin(),ionsLoaded.end());
787
 
 
788
 
                for(unsigned int ui=0;ui<ionsToLoad.size()-seenCount;ui++)
789
 
                {
790
 
                        //Keep swapping out bad entries until we find a good one
791
 
                        while(std::binary_search(ionsLoaded.begin(),ionsLoaded.end(),
792
 
                                                ionsToLoad[ui]) && ui!= ionsToLoad.size()-seenCount)
793
 
                        {
794
 
                                //Swap this "bad" ion out for a fresh one
795
 
                                std::swap(ionsToLoad[ui],ionsToLoad[ionsToLoad.size()-seenCount]);
796
 
                                seenCount++;
797
 
                        }
798
 
 
799
 
                }
800
 
                
801
 
                //Sort the vector front again, as we have disrupted the order during discard
802
 
                //(should be near sorted, so not too costly)
803
 
                //Ignore the back indicies,a as we wont use them anymore.
804
 
                //Being sorted means that we don't have to spin the disc backwards, and can jump forwards
805
 
                //every time.
806
 
                std::sort(ionsToLoad.begin(),ionsToLoad.end()-seenCount);
807
 
                //===
808
 
                
809
 
 
810
 
                unsigned int curProg = PROGRESS_REDUCE; 
811
 
                IONHIT hit;
812
 
                std::ios::pos_type  nextIonPos;
813
 
                unsigned int ionStart=0;
814
 
                for(size_t ui=0;ui<ionsToLoad.size()-seenCount; ui++)
815
 
                {
816
 
                        nextIonPos =  ionsToLoad[ui]*sizeof(IONHIT);
817
 
                        ionsLoaded.push_back(ionsToLoad[ui]);
818
 
                        
819
 
                        if(CFile.tellg() !=nextIonPos )
820
 
                                CFile.seekg(nextIonPos);
821
 
 
822
 
                        //Read the hit
823
 
                        CFile.read((char *)&hit,sizeof(IONHIT));
824
 
                        if(!CFile.good())
825
 
                                return POS_READ_FAIL;
826
 
 
827
 
        
828
 
                        //Reject the ion if it is not in the 
829
 
                        //target volume 
830
 
                        if(bound.containsPt(Point3D(hit.pos[0],hit.pos[1],hit.pos[2])))
831
 
                        {
832
 
                                posIons[pointCount].setHit(&hit);
833
 
                                //Data bytes stored in pos files are big
834
 
                                //endian. flip as required
835
 
                                #ifdef __LITTLE_ENDIAN__
836
 
                                        posIons[pointCount].switchEndian();     
837
 
                                #endif
838
 
                                //Check for nan. If we find one, abort
839
 
                                if(posIons[pointCount].hasNaN())
840
 
                                {
841
 
                                        delete[] buffer;
842
 
                                        return POS_NAN_LOAD_ERROR;      
843
 
                                }
844
 
 
845
 
                                pointCount++;
846
 
                        }
847
 
                        
848
 
                        //Update progress bar   
849
 
                        if(!curProg--)
850
 
                        {
851
 
 
852
 
                                progress= (unsigned int)((float)(pointCount)/((float)limitCount)*100.0f);
853
 
                                curProg=PROGRESS_REDUCE;
854
 
 
855
 
                                if(!(*callback)())
856
 
                                {
857
 
                                        delete[] buffer;
858
 
                                        posIons.clear();
859
 
                                        return POS_ABORT_FAIL;
860
 
                                        
861
 
                                }
862
 
                        }
863
 
                }
864
 
 
865
 
        //Keep loading until we can do no more, or we have enough.
866
 
        }while(pointCount < limitCount && ionsLoaded.size() != fileSize/RECORD_WIDTH); 
867
 
 
868
 
        delete[] buffer;
869
 
        return 0;
870
 
}
871
 
 
872
 
 
873
 
 
874
 
//!Load a pos file into a T of IonHits, excluding ions not within the bounds
875
 
template<class T>
876
 
unsigned int RestrictLoadPosFile(T &posIons,const char *posFile, const BoundCube &b,
877
 
                unsigned int &progress, bool (*callback)())
878
 
{
879
 
 
880
 
        ASSERT(b.isValid());
881
 
        //buffersize must be a power of two and at least sizeof(IONHIT)
882
 
        const unsigned int BUFFERSIZE=8192;
883
 
        char *buffer=new char[BUFFERSIZE];
884
 
        
885
 
        if(!buffer)
886
 
                return POS_ALLOC_FAIL;
887
 
 
888
 
        //open pos file
889
 
        std::ifstream CFile(posFile,std::ios::binary);
890
 
 
891
 
        if(!CFile)
892
 
        {
893
 
                delete[] buffer;
894
 
                return POS_OPEN_FAIL;
895
 
        }
896
 
        
897
 
        CFile.seekg(0,std::ios::end);
898
 
        size_t fileSize=CFile.tellg();
899
 
        
900
 
        if(!fileSize)
901
 
        {
902
 
                delete[] buffer;
903
 
                return POS_EMPTY_FAIL;
904
 
        }
905
 
        
906
 
        CFile.seekg(0,std::ios::beg);
907
 
        
908
 
        //calculate the number of points stored in the POS file
909
 
        IonHit hit;
910
 
        IONHIT *hitStruct;
911
 
        size_t pointCount=0;
912
 
        //regular case
913
 
        size_t curBufferSize=BUFFERSIZE;
914
 
        
915
 
        if(fileSize % sizeof(IONHIT))
916
 
        {
917
 
                delete[] buffer;
918
 
                return POS_SIZE_MODULUS_ERR;    
919
 
        }
920
 
 
921
 
        try
922
 
        {
923
 
                posIons.resize(fileSize/sizeof(IONHIT));
924
 
        }
925
 
        catch(std::bad_alloc)
926
 
        {
927
 
                return POS_ALLOC_FAIL;
928
 
        }
929
 
 
930
 
        
931
 
        while(fileSize < curBufferSize)
932
 
                curBufferSize = curBufferSize >> 1;
933
 
 
934
 
        //Technically this is dependant upon the buffer size.
935
 
        unsigned int curProg = PROGRESS_REDUCE; 
936
 
        size_t ionP=0;
937
 
        do
938
 
        {
939
 
                while((size_t)CFile.tellg() <= fileSize-curBufferSize)
940
 
                {
941
 
                        CFile.read(buffer,curBufferSize);
942
 
                        if(!CFile.good())
943
 
                        {
944
 
                                delete[] buffer;
945
 
                                return POS_READ_FAIL;
946
 
                        }
947
 
 
948
 
                        hitStruct = (IONHIT *)buffer; 
949
 
                        unsigned int ui;
950
 
                        for(ui=0; ui<curBufferSize; ui+=(sizeof(IONHIT)))
951
 
                        {
952
 
                                hit.setHit(hitStruct);
953
 
                                //Data bytes stored in pos files are big
954
 
                                //endian. flip as required
955
 
                                #ifdef __LITTLE_ENDIAN__
956
 
                                        hit.switchEndian();     
957
 
                                #endif
958
 
                                
959
 
                                if(hit.hasNaN())
960
 
                                {
961
 
                                        delete[] buffer;
962
 
                                        return POS_NAN_LOAD_ERROR;      
963
 
                                }
964
 
 
965
 
                                if(b.containsPt(hit.getPos()))
966
 
                                {
967
 
                                        posIons[ionP] = hit;
968
 
                                        ionP++;
969
 
                                        
970
 
                                        pointCount++;
971
 
                                }
972
 
 
973
 
                                hitStruct++;
974
 
                        }       
975
 
                        
976
 
                        if(!curProg--)
977
 
                        {
978
 
                                progress= (unsigned int)((float)(CFile.tellg())/((float)fileSize)*100.0f);
979
 
                                curProg=PROGRESS_REDUCE;
980
 
                                if(!(*callback)())
981
 
                                {
982
 
                                        delete[] buffer;
983
 
                                        posIons.clear();
984
 
                                        return POS_ABORT_FAIL;
985
 
                                        
986
 
                                }
987
 
                        }
988
 
                                
989
 
                }
990
 
 
991
 
                curBufferSize = curBufferSize >> 1 ;
992
 
        }while(curBufferSize >= sizeof(IONHIT));
993
 
 
994
 
        ASSERT((unsigned int)CFile.tellg() == fileSize);
995
 
        delete[] buffer;
996
 
 
997
 
        return 0;
998
 
}
999
 
 
1000
 
 
1001
 
//!Set the bounds from an array of ion hits
1002
 
BoundCube getIonDataLimits(const vector<IonHit> &p);//
 
281
unsigned int GenericLoadFloatFile(unsigned int inputnumcols, unsigned int outputnumcols, 
 
282
                unsigned int index[], vector<IonHit> &posIons,const char *posFile, 
 
283
                                unsigned int &progress, bool (*callback)());
 
284
 
 
285
 
 
286
unsigned int LimitLoadPosFile(unsigned int inputnumcols, unsigned int outputnumcols, unsigned int index[], 
 
287
                        vector<IonHit> &posIons,const char *posFile, size_t limitCount,
 
288
                                                unsigned int &progress, bool (*callback)(),bool strongRandom);
 
289
 
1003
290
#endif