00001
00002
00003
00004
00005 #ifndef BALL_DATATYPE_REGULARDATA1D_H
00006 #define BALL_DATATYPE_REGULARDATA1D_H
00007
00008 #ifndef BALL_COMMON_H
00009 # include <BALL/common.h>
00010 #endif
00011
00012 #ifndef BALL_SYSTEM_FILE_H
00013 # include <BALL/SYSTEM/file.h>
00014 #endif
00015
00016 #ifndef BALL_SYSTEM_BINARYFILEADAPTOR_H
00017 # include <BALL/SYSTEM/binaryFileAdaptor.h>
00018 #endif
00019
00020 #include <vector>
00021 #include <iostream>
00022 #include <fstream>
00023 #include <iterator>
00024 #include <algorithm>
00025
00026 namespace BALL
00027 {
00039 template <typename ValueType>
00040 class TRegularData1D
00041 {
00042 public:
00043
00044 BALL_CREATE(TRegularData1D<ValueType>)
00045
00046
00049
00051 typedef Position IndexType;
00053 typedef std::vector<ValueType> VectorType;
00055 typedef double CoordinateType;
00057 typedef typename std::vector<ValueType>::iterator Iterator;
00059 typedef typename std::vector<ValueType>::const_iterator ConstIterator;
00061
00062
00063
00064 typedef ValueType value_type;
00065 typedef typename std::vector<ValueType>::iterator iterator;
00066 typedef typename std::vector<ValueType>::const_iterator const_iterator;
00067 typedef typename std::vector<ValueType>::reference reference;
00068 typedef typename std::vector<ValueType>::const_reference const_reference;
00069 typedef typename std::vector<ValueType>::pointer pointer;
00070 typedef typename std::vector<ValueType>::difference_type difference_type;
00071 typedef typename std::vector<ValueType>::size_type size_type;
00072
00076
00078 TRegularData1D();
00079
00083 TRegularData1D(const TRegularData1D& data);
00084
00088 TRegularData1D(const CoordinateType& origin, const CoordinateType& dimension, const CoordinateType& spacing);
00089
00093 TRegularData1D(const IndexType& size);
00094
00098 TRegularData1D(const VectorType& data, const CoordinateType& origin = 0.0, const CoordinateType& dimension = 1.0);
00099
00101 virtual ~TRegularData1D();
00102
00104 virtual void clear();
00106
00107
00111
00116 TRegularData1D& operator = (const TRegularData1D<ValueType>& data);
00117
00122 TRegularData1D& operator = (const VectorType& data);
00123
00125
00129
00130 bool operator == (const TRegularData1D& data) const;
00131
00133 BALL_INLINE bool operator != (const TRegularData1D& data) const { return !this->operator == (data); }
00134
00136 BALL_INLINE bool empty() const { return data_.empty(); }
00137
00139 bool isInside(const CoordinateType& x) const;
00141
00145
00146 BALL_INLINE ConstIterator begin() const { return data_.begin(); }
00148 BALL_INLINE ConstIterator end() const { return data_.end(); }
00150 BALL_INLINE Iterator begin() { return data_.begin(); }
00152 BALL_INLINE Iterator end() { return data_.end(); }
00154
00158
00159
00160 BALL_INLINE size_type size() const { return data_.size(); }
00161 BALL_INLINE size_type max_size() const { return data_.max_size(); }
00162 BALL_INLINE void swap(TRegularData1D<ValueType>& data) { std::swap(*this, data); }
00163
00168 const ValueType& getData(const IndexType& index) const;
00169
00174 ValueType& getData(const IndexType& index);
00175
00180 const ValueType& operator [] (const IndexType& index) const { return data_[index]; }
00181
00186 ValueType& operator [] (const IndexType& index) { return data_[index]; }
00187
00196 ValueType operator () (const CoordinateType& x) const;
00197
00204 ValueType getInterpolatedValue(const CoordinateType& x) const;
00205
00212 void getEnclosingIndices(const CoordinateType& x, Position& lower, Position& upper) const;
00213
00218 void getEnclosingValues(const CoordinateType& x, ValueType& lower, ValueType& upper) const;
00219
00224 CoordinateType getCoordinates(const IndexType& index) const;
00225
00232 IndexType getClosestIndex(const CoordinateType& x) const;
00233
00240 IndexType getLowerIndex(const CoordinateType& x) const;
00241
00248 const ValueType& getClosestValue(const CoordinateType& x) const;
00249
00256 ValueType& getClosestValue(const CoordinateType& x);
00257
00259 BALL_INLINE IndexType getSize() const { return (IndexType)data_.size(); }
00260
00265 BALL_INLINE const CoordinateType& getOrigin() const { return origin_; }
00266
00271 BALL_INLINE const CoordinateType& getSpacing() const { return spacing_; }
00272
00275 BALL_INLINE void setOrigin(const CoordinateType& origin) { origin_ = origin; }
00276
00282 BALL_INLINE const CoordinateType& getDimension() const { return dimension_; }
00283
00289 BALL_INLINE void setDimension(const CoordinateType& dimension) { dimension_ = dimension; }
00290
00303 void resize(const IndexType& size);
00304
00314 void rescale(const IndexType& new_size);
00315
00319 ValueType calculateMean() const;
00320
00324 ValueType calculateSD() const;
00325
00329 void binaryWrite(const String& filename) const;
00330
00334 void binaryRead(const String& filename);
00336
00337
00338 protected:
00340 CoordinateType origin_;
00341
00343 CoordinateType dimension_;
00344
00346 CoordinateType spacing_;
00347
00349 VectorType data_;
00350
00352 typedef struct { ValueType bt[1024]; } BlockValueType;
00353 };
00354
00357 typedef TRegularData1D<float> RegularData1D;
00358
00359 template <typename ValueType>
00360 TRegularData1D<ValueType>::TRegularData1D()
00361 : origin_(0.0),
00362 dimension_(0.0),
00363 spacing_(1.0),
00364 data_()
00365 {
00366 }
00367
00368 template <typename ValueType>
00369 TRegularData1D<ValueType>::~TRegularData1D()
00370 {
00371 }
00372
00373 template <typename ValueType>
00374 TRegularData1D<ValueType>::TRegularData1D(const TRegularData1D<ValueType>& data)
00375 : origin_(data.origin_),
00376 dimension_(data.dimension_),
00377 spacing_(data.spacing_),
00378 data_()
00379 {
00380
00381 try
00382 {
00383 data_ = data.data_;
00384 }
00385 catch (std::bad_alloc&)
00386 {
00387 throw Exception::OutOfMemory(__FILE__, __LINE__, data.size() * sizeof(ValueType));
00388 }
00389 }
00390
00391 template <typename ValueType>
00392 TRegularData1D<ValueType>::TRegularData1D
00393 (const typename TRegularData1D<ValueType>::CoordinateType& origin,
00394 const typename TRegularData1D<ValueType>::CoordinateType& dimension,
00395 const typename TRegularData1D<ValueType>::CoordinateType& spacing)
00396 : origin_(origin),
00397 dimension_(dimension),
00398 spacing_(spacing),
00399 data_()
00400 {
00401
00402 size_type size = (size_type)(dimension_ / spacing_ + 1.0);
00403
00404
00405 try
00406 {
00407 data_.resize(size);
00408 }
00409 catch (std::bad_alloc&)
00410 {
00411 throw Exception::OutOfMemory(__FILE__, __LINE__, size * sizeof(ValueType));
00412 }
00413 }
00414
00415 template <typename ValueType>
00416 TRegularData1D<ValueType>::TRegularData1D
00417 (const typename TRegularData1D<ValueType>::VectorType& data,
00418 const typename TRegularData1D<ValueType>::CoordinateType& origin,
00419 const typename TRegularData1D<ValueType>::CoordinateType& dimension)
00420 : origin_(origin),
00421 dimension_(dimension),
00422 spacing_(dimension / ((double)data.size()-1)),
00423 data_()
00424 {
00425
00426 try
00427 {
00428 data_ = data;
00429 }
00430 catch (std::bad_alloc&)
00431 {
00432 throw Exception::OutOfMemory(__FILE__, __LINE__, data.size() * sizeof(ValueType));
00433 }
00434 }
00435
00436
00437 template <class ValueType>
00438 TRegularData1D<ValueType>::TRegularData1D
00439 (const typename TRegularData1D<ValueType>::IndexType& size)
00440 : origin_(0.0),
00441 dimension_(1.0),
00442 data_()
00443 {
00444
00445 spacing_ = dimension_ / (double)(size - 1);
00446
00447 try
00448 {
00449 data_.resize(size);
00450 }
00451 catch (std::bad_alloc&)
00452 {
00453 data_.resize(0);
00454 throw Exception::OutOfMemory(__FILE__, __LINE__, size * sizeof(ValueType));
00455 }
00456 }
00457
00458 template <typename ValueType>
00459 void TRegularData1D<ValueType>::clear()
00460 {
00461
00462
00463 static ValueType default_value = ValueType();
00464 std::fill(data_.begin(), data_.end(), default_value);
00465 }
00466
00467 template <typename ValueType>
00468 TRegularData1D<ValueType>& TRegularData1D<ValueType>::operator = (const TRegularData1D<ValueType>& rhs)
00469 {
00470
00471 origin_ = rhs.origin_;
00472 dimension_ = rhs.dimension_;
00473 spacing_ = rhs.spacing_;
00474 try
00475 {
00476 data_ = rhs.data_;
00477 }
00478 catch (std::bad_alloc&)
00479 {
00480 data_.resize(0);
00481 throw Exception::OutOfMemory(__FILE__, __LINE__, rhs.size() * sizeof(ValueType));
00482 }
00483
00484 return *this;
00485 }
00486
00487 template <typename ValueType>
00488 TRegularData1D<ValueType>& TRegularData1D<ValueType>::operator = (const VectorType& rhs)
00489 {
00490
00491 try
00492 {
00493 data_ = rhs;
00494 }
00495 catch (std::bad_alloc&)
00496 {
00497 data_.resize(0);
00498 throw Exception::OutOfMemory(__FILE__, __LINE__, rhs.size() * sizeof(ValueType));
00499 }
00500
00501 return *this;
00502 }
00503
00504 template <typename ValueType>
00505 bool TRegularData1D<ValueType>::operator == (const TRegularData1D<ValueType>& data) const
00506 {
00507 return (origin_ == data.origin_
00508 && dimension_ == data.dimension_
00509 && data_ == data.data_);
00510 }
00511
00512 template <class ValueType>
00513 BALL_INLINE
00514 bool TRegularData1D<ValueType>::isInside(const typename TRegularData1D<ValueType>::CoordinateType& r) const
00515 {
00516 return ((r >= origin_) && (r <= (origin_ + dimension_)));
00517 }
00518
00519 template <typename ValueType>
00520 BALL_INLINE
00521 const ValueType& TRegularData1D<ValueType>::getData(const IndexType& index) const
00522 {
00523 if (index >= data_.size())
00524 {
00525 throw Exception::OutOfGrid(__FILE__, __LINE__);
00526 }
00527 return data_[index];
00528 }
00529
00530 template <typename ValueType>
00531 BALL_INLINE
00532 ValueType& TRegularData1D<ValueType>::getData(const IndexType& index)
00533 {
00534 if (index >= data_.size())
00535 {
00536 throw Exception::OutOfGrid(__FILE__, __LINE__);
00537 }
00538 return data_[index];
00539 }
00540
00541 template <typename ValueType>
00542 void TRegularData1D<ValueType>::getEnclosingIndices
00543 (const typename TRegularData1D<ValueType>::CoordinateType& x,
00544 Position& lower, Position& upper) const
00545 {
00546 if (!isInside(x) || (data_.size() < 2))
00547 {
00548 throw Exception::OutOfGrid(__FILE__, __LINE__);
00549 }
00550 lower = (Position)floor((x - origin_) / spacing_);
00551 if (lower == data_.size() - 1)
00552 {
00553
00554 lower = data_.size() - 2;
00555 }
00556 upper = lower + 1;
00557 }
00558
00559 template <typename ValueType>
00560 void TRegularData1D<ValueType>::getEnclosingValues
00561 (const typename TRegularData1D<ValueType>::CoordinateType& x,
00562 ValueType& lower, ValueType& upper) const
00563 {
00564 Position lower_index;
00565 Position upper_index;
00566 getEnclosingIndices(x, lower_index, upper_index);
00567 lower = data_[lower_index];
00568 upper = data_[upper_index];
00569 }
00570
00571 template <typename ValueType>
00572 BALL_INLINE
00573 ValueType TRegularData1D<ValueType>::getInterpolatedValue(const CoordinateType& x) const
00574 {
00575 if (!isInside(x))
00576 {
00577 throw Exception::OutOfGrid(__FILE__, __LINE__);
00578 }
00579 return operator () (x);
00580 }
00581
00582 template <typename ValueType>
00583 BALL_INLINE
00584 typename TRegularData1D<ValueType>::CoordinateType TRegularData1D<ValueType>::getCoordinates
00585 (const typename TRegularData1D<ValueType>::IndexType& index) const
00586 {
00587 if ((index >= data_.size()) || (data_.size() == 0))
00588 {
00589 throw Exception::OutOfGrid(__FILE__, __LINE__);
00590 }
00591
00592 return (CoordinateType)(origin_ + (double)index / ((double)data_.size()-1) * dimension_);
00593 }
00594
00595 template <typename ValueType>
00596 BALL_INLINE
00597 typename TRegularData1D<ValueType>::IndexType TRegularData1D<ValueType>::getClosestIndex(const CoordinateType& x) const
00598 {
00599 if ((x < origin_) || (x > (origin_ + dimension_)))
00600 {
00601 throw Exception::OutOfGrid(__FILE__, __LINE__);
00602 }
00603
00604 return (IndexType)(size_type)floor((x - origin_) / spacing_ + 0.5);
00605 }
00606
00607 template <typename ValueType>
00608 BALL_INLINE
00609 typename TRegularData1D<ValueType>::IndexType TRegularData1D<ValueType>::getLowerIndex(const CoordinateType& x) const
00610 {
00611 if ((x < origin_) || (x > (origin_ + dimension_)))
00612 {
00613 throw Exception::OutOfGrid(__FILE__, __LINE__);
00614 }
00615
00616 return (IndexType)(size_type)floor((x - origin_) / spacing_);
00617 }
00618
00619 template <typename ValueType>
00620 BALL_INLINE
00621 const ValueType& TRegularData1D<ValueType>::getClosestValue(const CoordinateType& x) const
00622 {
00623 if ((x < origin_) || (x > (origin_ + dimension_)))
00624 {
00625 throw Exception::OutOfGrid(__FILE__, __LINE__);
00626 }
00627
00628
00629 size_type index = (size_type)floor((x - origin_) / spacing_ + 0.5);
00630 return data_[index];
00631 }
00632
00633 template <typename ValueType>
00634 BALL_INLINE
00635 ValueType& TRegularData1D<ValueType>::getClosestValue(const CoordinateType& x)
00636 {
00637 if ((x < origin_) || (x > (origin_ + dimension_)))
00638 {
00639 throw Exception::OutOfGrid(__FILE__, __LINE__);
00640 }
00641
00642
00643 size_type index = (size_type)floor((x - origin_) / spacing_ + 0.5);
00644 return data_[index];
00645 }
00646
00647 template <typename ValueType>
00648 BALL_INLINE
00649 ValueType TRegularData1D<ValueType>::calculateMean() const
00650 {
00651 IndexType data_points = this->getSize();
00652 ValueType mean = 0;
00653 for (IndexType i = 0; i < data_points; i++)
00654 {
00655 mean += data_[i];
00656 }
00657 mean /= data_points;
00658 return mean;
00659 }
00660
00661 template <typename ValueType>
00662 BALL_INLINE
00663 ValueType TRegularData1D<ValueType>::calculateSD() const
00664 {
00665 IndexType data_points = this->getSize();
00666 ValueType stddev = 0;
00667 ValueType mean = this->calculateMean();
00668 for (IndexType i = 0; i < data_points; i++)
00669 {
00670 stddev += (pow(data_[i]-mean,2));
00671 }
00672 stddev /= (data_points-1);
00673 stddev = sqrt(stddev);
00674 return stddev;
00675 }
00676
00677 template <typename ValueType>
00678 BALL_INLINE
00679 ValueType TRegularData1D<ValueType>::operator () (const CoordinateType& x) const
00680 {
00681 size_type left_index = (size_type)floor((x - origin_) / spacing_);
00682 if (left_index == data_.size() - 1)
00683 {
00684
00685 return data_[data_.size() - 1];
00686 }
00687
00688
00689 double d = 1.0 - (((x - origin_) - (double)left_index * spacing_) / spacing_);
00690 return data_[left_index] * d + (1.0 - d) * data_[left_index + 1];
00691 }
00692
00693 template <typename ValueType>
00694 void TRegularData1D<ValueType>::resize
00695 (const typename TRegularData1D<ValueType>::IndexType& new_size)
00696 {
00697
00698 if (data_.size() > 0)
00699 {
00700 dimension_ *= (double)new_size / (double)data_.size();
00701 }
00702
00703
00704 try
00705 {
00706 data_.resize(new_size);
00707 }
00708 catch (std::bad_alloc&)
00709 {
00710
00711 data_.resize(0);
00712 throw Exception::OutOfMemory(__FILE__, __LINE__, new_size * sizeof(ValueType));
00713 }
00714 }
00715
00716 template <typename ValueType>
00717 void TRegularData1D<ValueType>::rescale
00718 (const typename TRegularData1D<ValueType>::IndexType& new_size)
00719 {
00720
00721 if (new_size == (IndexType)data_.size())
00722 {
00723 return;
00724 }
00725
00726
00727 try
00728 {
00729
00730 if (data_.size() == 0)
00731 {
00732
00733 data_.resize(new_size);
00734 return;
00735 }
00736
00737
00738
00739 if ((data_.size() == 1) && (new_size > 1))
00740 {
00741 ValueType old_value = data_[0];
00742 data_.resize(new_size);
00743 for (IndexType i = 1; i < new_size; i++)
00744 {
00745 data_[i] = old_value;
00746 }
00747
00748 return;
00749 }
00750
00751
00752
00753 VectorType new_data(new_size);
00754 CoordinateType factor1 = (CoordinateType)data_.size() / (CoordinateType)new_size;
00755 CoordinateType factor2 = (CoordinateType)(data_.size() - 1) / (new_size - 1);
00756
00757 for (Size i = 0; i < new_size; i++)
00758 {
00759
00760
00761 IndexType old_idx = (IndexType)((CoordinateType)i * factor1);
00762
00763
00764 if (old_idx >= (data_.size() - 1))
00765 {
00766 old_idx = data_.size() - 2;
00767 }
00768 CoordinateType factor3 = (CoordinateType)i * factor2 - (CoordinateType)old_idx;
00769 new_data[i] = data_[old_idx] * (1 - factor3) + factor3 * data_[old_idx + 1];
00770 }
00771
00772
00773 data_ = new_data;
00774 }
00775 catch (std::bad_alloc&)
00776 {
00777
00778 data_.resize(0);
00779 throw Exception::OutOfMemory(__FILE__, __LINE__, new_size * sizeof(ValueType));
00780 }
00781 }
00782
00785
00786 template <typename ValueType>
00787 std::ostream& operator << (std::ostream& os, const TRegularData1D<ValueType>& data)
00788 {
00789
00790 os << data.getOrigin() << std::endl
00791 << data.getOrigin() + data.getDimension() << std::endl
00792 << data.getSize() - 1 << std::endl;
00793
00794
00795 std::copy(data.begin(), data.end(), std::ostream_iterator<ValueType>(os, "\n"));
00796 return os;
00797 }
00798
00800 template <typename ValueType>
00801 std::istream& operator >> (std::istream& is, TRegularData1D<ValueType>& grid)
00802 {
00803 typename TRegularData1D<ValueType>::CoordinateType origin;
00804 typename TRegularData1D<ValueType>::CoordinateType dimension;
00805 typename TRegularData1D<ValueType>::IndexType size;
00806
00807 is >> origin;
00808 is >> dimension;
00809 is >> size;
00810
00811 dimension -= origin;
00812 size++;
00813
00814 grid.resize(size);
00815 grid.setOrigin(origin);
00816 grid.setDimension(dimension);
00817
00818 std::copy(std::istream_iterator<ValueType>(is),
00819 std::istream_iterator<ValueType>(),
00820 grid.begin());
00821
00822
00823 return is;
00824 }
00825
00826 template <typename ValueType>
00827 void TRegularData1D<ValueType>::binaryWrite(const String& filename) const
00828 {
00829 File outfile(filename, std::ios::out|std::ios::binary);
00830 if (!outfile.isValid())
00831 {
00832 throw Exception::FileNotFound(__FILE__, __LINE__, filename);
00833 }
00834
00835 BinaryFileAdaptor<BlockValueType> adapt_block;
00836 BinaryFileAdaptor<ValueType> adapt_single;
00837
00838
00839 BinaryFileAdaptor<CoordinateType> adapt_coordinate;
00840 BinaryFileAdaptor<Size> adapt_size;
00841
00842 adapt_size.setData(data_.size());
00843 outfile << adapt_size;
00844
00845 adapt_coordinate.setData(origin_);
00846 outfile << adapt_coordinate;
00847
00848 adapt_coordinate.setData(dimension_);
00849 outfile << adapt_coordinate;
00850
00851 adapt_coordinate.setData(spacing_);
00852 outfile << adapt_coordinate;
00853
00854
00855 Index window_pos = 0;
00856 while (((int)data_.size() - (1024 + window_pos)) >= 0 )
00857 {
00858 adapt_block.setData(*(BlockValueType*)&(data_[window_pos]));
00859 outfile << adapt_block;
00860 window_pos += 1024;
00861 }
00862
00863
00864 for (Size i = window_pos; i < data_.size(); i++)
00865 {
00866 adapt_single.setData(data_[i]);
00867 outfile << adapt_single;
00868 }
00869
00870
00871 outfile.close();
00872 }
00873
00874 template <typename ValueType>
00875 void TRegularData1D<ValueType>::binaryRead(const String& filename)
00876 {
00877 File infile(filename, std::ios::in|std::ios::binary);
00878 if (!infile.isValid()) throw Exception::FileNotFound(__FILE__, __LINE__, filename);
00879
00880 BinaryFileAdaptor<BlockValueType> adapt_block;
00881 BinaryFileAdaptor<ValueType> adapt_single;
00882
00883
00884 BinaryFileAdaptor<CoordinateType> adapt_coordinate;
00885 BinaryFileAdaptor<Size> adapt_size;
00886
00887 infile >> adapt_size;
00888 Size new_size = adapt_size.getData();
00889
00890 infile >> adapt_coordinate;
00891 origin_ = adapt_coordinate.getData();
00892
00893 infile >> adapt_coordinate;
00894 dimension_ = adapt_coordinate.getData();
00895
00896 infile >> adapt_coordinate;
00897 spacing_ = adapt_coordinate.getData();
00898
00899 data_.resize(new_size);
00900
00901
00902 Index window_pos = 0;
00903
00904 while ( ((int)data_.size() - (1024 + window_pos)) >= 0 )
00905 {
00906 infile >> adapt_block;
00907 *(BlockValueType*)(&(data_[window_pos])) = adapt_block.getData();
00908
00909
00910
00911
00912
00913
00914 window_pos+=1024;
00915 }
00916
00917
00918 for (Size i=window_pos; i<data_.size(); i++)
00919 {
00920 infile >> adapt_single;
00921 data_[i] = adapt_single.getData();
00922 }
00923
00924
00925 infile.close();
00926 }
00927 }
00928
00929 #endif // BALL_DATATYPE_REGULARDATA1D_H