Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CartGrid.hh
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file /grid/src/core/grid/Grid.hh
11 /// @author Sam DeLuca
12 
13 #ifndef INCLUDED_core_grid_CartGrid_hh
14 #define INCLUDED_core_grid_CartGrid_hh
15 
16 
18 #include <core/types.hh>
19 
20 #include <numeric/xyzVector.hh>
21 
22 #include <utility/vector1.hh>
23 #include <utility/tools/make_vector.hh>
24 #include <utility/string_util.hh>
25 #include <utility/json_spirit/json_spirit_value.h>
26 #include <utility/pointer/ReferenceCount.hh>
27 #include <utility/pointer/owning_ptr.hh>
28 #include <utility/vector0.fwd.hh>
29 #include <utility/io/izstream.hh>
30 #include <utility/exit.hh>
31 #include <utility/Binary_Util.hh>
32 
33 #include <ObjexxFCL/string.functions.hh>
34 
35 #include <algorithm>
36 
37 
38 namespace core {
39 namespace grid {
40 
41 template <typename T>
42 class CartGrid : public utility::pointer::ReferenceCount
43 {
44 public:
46 
48  nX_(0), nY_(0), nZ_(0),
49  lX_(0.0), lY_(0.0), lZ_(0.0),
50  bX_(0.0), bY_(0.0), bZ_(0.0),
51  tX_(0.0), tY_(0.0), tZ_(0.0),
52  name_("default"),
53  npoints_(0),
54  fullyOccupied_(false),
55  zones_(NULL)
56  {
57 
58  }
59 
60  virtual ~CartGrid()
61  {
62  if (zones_ !=NULL)
63  {
64  delete [] zones_;
65  zones_ = NULL;
66  }
67  }
68 
69 /*
70  std::ostream & operator<< (Grid<T> const & mygrid)
71  {
72  os <<mygrid.its_bX_ << " " << mygrid.its_bY_ << " " << mygrid.its_bZ_ << " | "
73  << mygrid.its_tX_ << " " << mygrid.its_tY_ << " " << mygrid.its_tZ_;
74  return os;
75  }
76 */
77 
79  {
80  bX_ = x;
81  bY_ = y;
82  bZ_ = z;
83 
84  this->setTop();
85  }
86 
87  void setDimensions(int nX, int nY, int nZ, core::Real lX, core::Real lY, core::Real lZ)
88  {
89  nX_ = nX;
90  nY_ = nY;
91  nZ_ = nZ;
92 
93  lX_ = lX;
94  lY_ = lY;
95  lZ_ = lZ;
96 
97  this->setTop();
98  }
99 
100  void set_name(std::string const & name)
101  {
102  name_ = name;
103  }
104 
106  {
107  return name_;
108  }
109 
110  int longestSide() const
111  {
112  int ls = this->nX_;
113  if (this->nY_ > ls) ls = this->nY_;
114  if (this->nZ_ > ls) ls = this->nZ_;
115 
116  return ls;
117  }
118  bool equalDimensions(CartGrid<T> const & rhs) const
119  {
120  if (nX_ != rhs.nX_)
121  return false;
122  if (nY_ != rhs.nY_)
123  return false;
124  if (nZ_ != rhs.nZ_)
125  return false;
126 
127  if (lX_ != rhs.lX_)
128  return false;
129  if (lY_ != rhs.lY_)
130  return false;
131  if (lZ_ != rhs.lZ_)
132  return false;
133 
134  return true;
135  }
136 
137  bool equalBase(CartGrid<T> const & rhs) const
138  {
139  if (std::abs(this->bX_ - rhs.bX_) > 0.01) return false;
140  if (std::abs(this->bY_ - rhs.bY_) > 0.01) return false;
141  if (std::abs(this->bZ_ - rhs.bZ_) > 0.01) return false;
142  return true;
143  }
144 
146  {
147  if (x < bX_ || x > tX_)
148  {
149  return false;
150  }
151  if (y < bY_ || y > tY_)
152  {
153  return false;
154  }
155  if (z < bZ_ || z > tZ_)
156  {
157  return false;
158  }
159 
160  return true;
161  }
162 
163  bool setupZones()
164  {
165  if (zones_ != NULL)
166  {
167  //delete zones_;
168  delete[] zones_;
169  zones_ = NULL;
170  }
171 
172  npoints_ = nX_*nY_*nZ_;
173  zones_ = new T[npoints_];
174 
175  return true;
176  }
177 
179  {
180  bX_ += x;
181  bY_ += y;
182  bZ_ += z;
183  this->setTop();
184  }
185 
186  bool setValue(int ix, int iy, int iz, T value)
187  {
188  if (value == 0)
189  {
190  fullyOccupied_ = false;
191  }
192 
193  int index = this->get_index(ix, iy, iz);
194  assert( index >= 0 && index < npoints_ );
195  this->zones_[index] = value;
196  return true;
197  }
198 
199 
200  bool setValue(core::Real fx, core::Real fy, core::Real fz, T value)
201  {
202  if (value == 0) {
203  fullyOccupied_ = false;
204  }
205 
206  int ix = int((fx - bX_)/lX_);
207  if (ix < 0 || ix >= nX_) return 0;
208 
209  int iy = int((fy - bY_)/lY_);
210  if (iy < 0 || iy >= nY_) return 0;
211 
212  int iz = int((fz - bZ_)/lZ_);
213  if (iz < 0 || iz >= nZ_) return 0;
214 
215  int index = this->get_index(ix,iy,iz);
216  assert( index >= 0 && index < npoints_ );
217  this->zones_[index] = value;
218  return true;
219  }
220 
221  T getValue(int ix, int iy, int iz) const
222  {
223  int index = this->get_index(ix, iy, iz);
224  return this->getValue(index);
225  }
226 
228  {
229  // --- round down --- //
230  int ix = int((fx - bX_)/lX_);
231  if (ix < 0 || ix >= nX_) return 0;
232 
233  int iy = int((fy - bY_)/lY_);
234  if (iy < 0 || iy >= nY_) return 0;
235 
236  int iz = int((fz - bZ_)/lZ_);
237  if (iz < 0 || iz >= nZ_) return 0;
238 
239  int index = ix*(nY_*nZ_) + iy*(nZ_) + iz;
240  return this->zones_[index];
241  }
242 
243  void zero()
244  {
245  for (int i=0; i < npoints_; i++)
246  {
247  this->zones_[i] = 0;
248  }
249  }
250 
251  void setFullOccupied(T value)
252  {
253  for (int i=0; i < npoints_; i++)
254  {
255  this->zones_[i] = value;
256  }
257  fullyOccupied_ = true;
258  }
259 
260  void clone(CartGrid<T> & copy) const {
261  // copy over gross information
262  copy.nX_ = this->nX_;
263  copy.nY_ = this->nY_;
264  copy.nZ_ = this->nZ_;
265 
266  copy.lX_ = this->lX_;
267  copy.lY_ = this->lY_;
268  copy.lZ_ = this->lZ_;
269 
270  copy.bX_ = this->bX_;
271  copy.bY_ = this->bY_;
272  copy.bZ_ = this->bZ_;
273 
274  copy.tX_ = this->tX_;
275  copy.tY_ = this->tY_;
276  copy.tZ_ = this->tZ_;
277 
278  copy.name_ = this->name_;
279 
280  copy.setupZones();
281 
282  for (int i=0; i < this->npoints_; i++) {
283  copy.zones_[i] = this->zones_[i];
284  }
285  }
286 
288  int minx = this->nX_;
289  int miny = this->nY_;
290  int minz = this->nZ_;
291 
292  int maxx = 0;
293  int maxy = 0;
294  int maxz = 0;
295 
296  for (int ix=0; ix < this->nX_; ix++) {
297  for (int iy=0; iy < this->nY_; iy++) {
298  for (int iz=0; iz < this->nZ_; iz++) {
299  if (this->getValue(ix,iy,iz)) {
300  minx = std::min(minx,ix);
301  miny = std::min(miny,iy);
302  minz = std::min(minz,iz);
303 
304  maxx = std::max(maxx,ix);
305  maxy = std::max(maxy,iy);
306  maxz = std::max(maxz,iz);
307  }
308  }
309  }
310  }
311 
312  if (maxx*maxy*maxz == 0) {
313  return; // no change
314  }
315 
316  CartGrid<T> tmpgrid;
317  this->clone(tmpgrid);
318 
319  int nx = maxx - minx + 1;
320  int ny = maxy - miny + 1;
321  int nz = maxz - minz + 1;
322 
323  this->nX_ = nx;
324  this->nY_ = ny;
325  this->nZ_ = nz;
326 
327  this->bX_ += minx*this->lX_;
328  this->bY_ += miny*this->lY_;
329  this->bZ_ += minz*this->lZ_;
330 
331  this->setupZones();
332 
333  int index2=0;
334  int value = 0;
335  for (int i=0; i < nx; i++) {
336  for (int j=0; j < ny; j++) {
337  for (int k=0; k < nz; k++) {
338  index2 = tmpgrid.get_index(minx+i, miny+j, minz+k);
339  value = tmpgrid.getValue(index2);
340  this->setValue(i,j,k,value);
341  }
342  }
343  }
344  }
345 
347  int istart, iend, jstart, jend, kstart, kend;
348  for (int i=0; i < input->its_nX_; i++) {
349  for (int j=0; j < input->its_nY_; j++) {
350  for (int k=0; k < input->its_nZ_; k++) {
351  if (input->getValue(i,j,k) != 0) {
352  istart = std::max(0, (i-amount));
353  iend = std::min(input->its_nX_, (i+amount));
354 
355  jstart = std::max(0, (j-amount));
356  jend = std::min(input->its_nY_, (j+amount));
357 
358  kstart = std::max(0, (k-amount));
359  kend = std::min(input->its_nZ_, (k+amount));
360 
361  for (int ii=istart; ii < iend; ii++) {
362  for (int jj=jstart; jj < jend; jj++) {
363  for (int kk=kstart; kk < kend; kk++) {
364  if (original->getValue(ii,jj,kk) != 0) {
365  this->setValue(ii,jj,kk,1);
366  }
367  }
368  }
369  }
370  }
371  }
372  }
373  }
374  }
375 
376  void read(std::string const & filename) {
377  //std::ifstream file;
378  utility::io::izstream file;
379  std::istringstream line_stream;
380 
381  file.open(filename.c_str());
382 
383  if (!file) {
384  std::cout << "read_gridfile - unable to open gridfile:" << filename << std::endl;
385  std::exit( EXIT_FAILURE );
386  }
387 
388  std::string line;
389  std::string keyword;
390  std::string name;
391  core::Real bx=0.0, by=0.0, bz=0.0;
392  core::Real lx=0.0, ly=0.0, lz=0.0;
393  T occupied(0);
394  int nx=0, ny=0, nz=0;
395  int ix=0, iy=0, iz=0;
396 
397  while(file) {
398  getline(file, line);
399 
400 
401  if (ObjexxFCL::is_blank(line)) {
402  ix++;
403  iy=0;
404  iz=0;
405  continue;
406  }
407 
408  line_stream.clear();
409  line_stream.str(line);
410  line_stream.seekg( std::ios::beg );
411 
412  line_stream >> keyword;
413  if (keyword == "NAME:") {
414  line_stream >> name;
415  this->set_name(name);
416  }
417  else if (keyword == "BASE:") {
418  line_stream >> bx >> by >> bz;
419  this->setBase(bx, by, bz);
420  } else if (keyword == "SIZE:") {
421  line_stream >> nx >> ny >> nz;
422  } else if (keyword == "LENGTH:") {
423  line_stream >> lx >> ly >> lz;
424  this->setDimensions(nx, ny, nz, lx, ly, lz);
425  this->setupZones();
426  } else {
427  line_stream.seekg( std::ios::beg );
428  iz = 0;
429  for (int iz=0; iz < nz; iz++) {
430  line_stream >> occupied;
431  this->setValue(ix,iy,iz,occupied);
432  }
433  iy++;
434  }
435  }
436 
437  file.close();
438  }
439 
440  void write(std::string const & filename) const {
441  std::ofstream file;
442  file.open(filename.c_str());
443  file << "NAME: " << this->get_name() << std::endl;
444  file << "BASE: " << this->bX_ << " " << this->bY_ << " " << this->bZ_ << std::endl;
445  file << "SIZE: " << this->nX_ << " " << this->nY_ << " " << this->nZ_ << std::endl;
446  file << "LENGTH: " << this->lX_ << " " << this->lY_ << " " << this->lZ_ << std::endl;
447 
448  for (int i=0; i < this->nX_; i++) {
449  for (int j=0; j < this->nY_; j++) {
450  for (int k=0; k < this->nZ_; k++) {
451  file << this->getValue(i,j,k) << " ";
452  }
453  file << std::endl;
454  }
455  file << std::endl;
456  }
457  file.close();
458  }
459 
460  bool isFullyOccupied() const {
461  return fullyOccupied_;
462  }
463 
464  bool isEmpty() const {
465  for (int i=0; i < npoints_; i++) {
466  if (this->zones_[i] != 0) {
467  return false;
468  }
469  }
470  return true;
471  }
472 
473  utility::json_spirit::Value serialize() const
474  {
475  using utility::json_spirit::Pair;
476  using utility::json_spirit::Value;
477  using utility::json_spirit::Array;
478  Pair name("name",this->get_name());
479  Pair base("base",utility::tools::make_vector(Value(this->bX_),Value(this->bY_),Value(this->bZ_)));
480  Pair size("size",utility::tools::make_vector(Value(this->nX_),Value(this->nY_),Value(this->nZ_)));
481  Pair length("length",utility::tools::make_vector(Value(this->lX_),Value(this->lY_),Value(this->lZ_)));
482 
483  std::string point_data;
484  utility::encode6bit((unsigned char*)zones_,npoints_*sizeof(T),point_data);
485 
486  utility::json_spirit::Pair data("data",Value(point_data));
487 
488  return utility::json_spirit::Value( utility::tools::make_vector(name,base,size,length,data) );
489 
490  }
491 
492  void deserialize(utility::json_spirit::mObject grid_data)
493  {
494  std::string name = grid_data["name"].get_str();
495 
496  utility::json_spirit::mArray base_data = grid_data["base"].get_array();
497  assert(base_data.size() == 3);
498 
499  core::Real bX = base_data[0].get_real();
500  core::Real bY = base_data[1].get_real();
501  core::Real bZ = base_data[2].get_real();
502 
503  utility::json_spirit::mArray size_data = grid_data["size"].get_array();
504  assert(size_data.size() == 3);
505 
506  int nX = size_data[0].get_int();
507  int nY = size_data[1].get_int();
508  int nZ = size_data[2].get_int();
509 
510  utility::json_spirit::mArray length_data = grid_data["length"].get_array();
511  assert(length_data.size() == 3);
512 
513  core::Real lX = length_data[0].get_real();
514  core::Real lY = length_data[1].get_real();
515  core::Real lZ = length_data[2].get_real();
516 
517  this->set_name(name);
518  this->setBase(bX,bY,bZ);
519  this->setDimensions(nX, nY, nZ, lX, lY, lZ);
520  this->setupZones();
521 
522  std::string point_data = grid_data["data"].get_str();
523  utility::decode6bit((unsigned char*)zones_,point_data);
524 
525  }
526 
528  int ngrids = static_cast<int>(list_grids.size());
529 
530  this->zero();
531  T curr_value, new_value;
532  for (int i=0; i < ngrids; i++) {
533  if (!this->equalDimensions(*(list_grids[i]))) {
534  return;
535  }
536  if (!this->equalBase(*(list_grids[i]))) {
537  return;
538  }
539 
540  for (int j=0; j < this->its_npoints; j++) {
541  curr_value = this->getValue(j);
542  new_value = list_grids[i]->getValue(j);
543  curr_value += new_value;
544  this->setValue(j,curr_value);
545  }
546  }
547  }
548 
549  void expand(int expansion) {
550  this->bX_ -= this->lX_*core::Real(expansion);
551  this->bY_ -= this->lY_*core::Real(expansion);
552  this->bZ_ -= this->lZ_*core::Real(expansion);
553 
554  this->nX_ += 2*expansion;
555  this->nY_ += 2*expansion;
556  this->nZ_ += 2*expansion;
557 
558  this->setupZones();
559  }
560 
561  void split(int nsplits, int igrid, core::Real pad, utility::pointer::owning_ptr<CartGrid<T> > grid) {
562  int tsplits = nsplits*nsplits*nsplits;
563  if (igrid < 0 || igrid >= tsplits) {
564  utility_exit_with_message("accessing split out of bounds");
565  }
566 
567  int split_x = int(core::Real(this->nX_)/core::Real(nsplits)) + 1;
568  int split_y = int(core::Real(this->nY_)/core::Real(nsplits)) + 1;
569  int split_z = int(core::Real(this->nZ_)/core::Real(nsplits)) + 1;
570 
571  int iz = int(igrid / (nsplits*nsplits));
572  int rem = igrid - (iz*nsplits*nsplits);
573  int iy = int(rem/nsplits);
574  int ix = rem - (iy*nsplits);
575 
576  int padx = int((pad/lX_)-0.1);
577  int pady = int((pad/lY_)-0.1);
578  int padz = int((pad/lZ_)-0.1);
579 
580  int leftx = padx;
581  int rightx = padx;
582  int lefty = pady;
583  int righty = pady;
584  int leftz = padz;
585  int rightz = padz;
586 
587  if (ix == 0)
588  {
589  leftx = 0;
590  }
591  if (iy == 0)
592  {
593  lefty = 0;
594  }
595  if (iz == 0)
596  {
597  leftz = 0;
598  }
599 
600  if (ix == nsplits-1)
601  {
602  rightx = 0;
603  }
604  if (iy == nsplits-1)
605  {
606  righty = 0;
607  }
608  if (iz == nsplits-1)
609  {
610  rightz = 0;
611  }
612 
613  grid->its_nX_ = split_x+leftx+rightx;
614  grid->its_nY_ = split_y+lefty+righty;
615  grid->its_nZ_ = split_z+leftz+rightz;
616 
617  core::Real bx = this->its_bX + ix*split_x*(this->lX_) - padx*(this->lX_);
618  core::Real by = this->its_bY + iy*split_y*(this->lY_) - pady*(this->lY_);
619  core::Real bz = this->its_bZ + iz*split_z*(this->lZ_) - padz*(this->lZ_);
620 
621  grid->its_bX_ = std::max(this->bX_, bx);
622  grid->its_bY_ = std::max(this->bY_, by);
623  grid->its_bZ_ = std::max(this->bZ_, bz);
624 
625  grid->its_lX_ = this->lX_;
626  grid->its_lY_ = this->lY_;
627  grid->its_lZ_ = this->lZ_;
628 
629 
630  // copy over grid data
631  grid->setDimensions(grid->its_nX_,grid->its_nY_,grid->its_nZ_,grid->its_lX_,grid->its_lY_,grid->its_lZ_);
632  grid->setupZones();
633  grid->zero();
634 
635  int xstart = std::max(0,ix*split_x-padx);
636  int ystart = std::max(0,iy*split_y-pady);
637  int zstart = std::max(0,iz*split_z-padz);
638 
639  for (int i=0; i < grid->its_nX_; i++) {
640  for (int j=0; j < grid->its_nY_; j++) {
641  for (int k=0; k < grid->its_nZ_; k++) {
642  int value = this->getValue(xstart+i,ystart+j,zstart+k);
643  if (value == -1) value = 0;
644  grid->setValue(i,j,k,value);
645  }
646  }
647  }
648  }
649 
651  {
652  return core::Vector(bX_, bY_, bZ_);
653  }
654 
656  {
657  return core::Vector(tX_, tY_, tZ_);
658  }
659 
660  void getNumberOfPoints(int & x, int & y, int & z) const
661  {
662  x = nX_;
663  y = nY_;
664  z = nZ_;
665  }
666 
667  GridPt gridpt(Vector const & coords) const
668  {
669  // Round down.
670  // Just casting to int will give wrong values for points outside the grid.
671  return GridPt(
672  static_cast<int>(std::floor((coords.x() - bX_)/lX_)),
673  static_cast<int>(std::floor((coords.y() - bY_)/lY_)),
674  static_cast<int>(std::floor((coords.z() - bZ_)/lZ_))
675  );
676 
677  }
678 
679  Vector coords(GridPt const & gridpt) const
680  {
681  return Vector(
682  (bX_ + (gridpt.x() + 0.5)*lX_),
683  (bY_ + (gridpt.y() + 0.5)*lY_),
684  (bZ_ + (gridpt.z() + 0.5)*lZ_)
685  );
686  }
687 
688 
689  T getValue(GridPt const & gridpt) const
690  {
691  return getValue(gridpt.x(), gridpt.y(), gridpt.z());
692  }
693 
694  T getValue(Vector const & coords) const
695  {
696  return getValue(coords.x(), coords.y(), coords.z());
697  }
698 
699  T getMinValue() const
700  {
701  return *std::min_element(zones_,zones_+npoints_);
702  }
703 
704  T getMaxValue() const
705  {
706  return *std::max_element(zones_,zones_+npoints_);
707  }
708 
709  void setValue(GridPt const & gridpt, T value)
710  {
711  setValue(gridpt.x(), gridpt.y(), gridpt.z(), value);
712  }
713 
714  void setValue(Vector const & coords, T value)
715  {
716  setValue(coords.x(), coords.y(), coords.z(), value);
717  }
718 
719  /// @details This format was choosen because it's space-efficient for small
720  /// integer values (such as are typically stored in grids) and PyMOL can read it.
721  /// Typical extension is .brix or .omap
723  {
724  std::ofstream out( filename.c_str() );
725  write_to_BRIX(out);
726  out.close();
727  }
728 
729  void write_to_BRIX(std::ostream & out)
730  {
731  int const plus = 127; // to convert values to unsigned bytes
732  // Crystallographic maps always expect one grid point to be at the origin.
733  // This may shift our map slightly...
734  GridPt origin = gridpt(Vector(0.,0.,0.));
735  out << ":-)"; // magic number
736  out << " Origin " << -origin.x() << ' ' << -origin.y() << ' ' << -origin.z() ; // starting indices for grid points actually present
737  out << " Extent " << nX_ << ' ' << nY_ << ' ' << nZ_ ; // number of grid points in each dimension
738  out << " Grid " << nX_ << ' ' << nY_ << ' ' << nZ_ ; // number of grid points in one unit cell
739  out << " Cell " << nX_*lX_ << ' ' << nY_*lY_ << ' ' << nZ_*lZ_ << " 90.0 90.0 90.0"; // dimensions of unit cell
740  out << " Prod 1 Plus " << plus << " Sigma 1\f";
741  // Now pad with spaces until we've writen 512 characters:
742  for(long i = out.tellp(); i < 512; ++i) out << ' ';
743  // Data stored in (padded) 8x8x8 blocks with X fast, Y medium, Z slow
744  typedef unsigned char ubyte;
745  for(int zz = 0; zz < nZ_; zz += 8) {
746  for(int yy = 0; yy < nY_; yy += 8) {
747  for(int xx = 0; xx < nX_; xx += 8) {
748  for(int z = zz, z_end = zz+8; z < z_end; ++z) {
749  for(int y = yy, y_end = yy+8; y < y_end; ++y) {
750  for(int x = xx, x_end = xx+8; x < x_end; ++x) {
751  if( x < nX_ && y < nY_ && z < nZ_ ) out << ubyte( getValue(x, y, z) + plus );
752  else out << ubyte( 0 + plus );
753  }
754  }
755  }
756  }
757  }
758  }
759  }
760 
761 
762 // Work in progress:
763 /*
764 
765  //shamelessly copy/pasted from core/scoring/electron_density
766  //I should really just make this a templated non-member function someplace
767  void write_to_MRC(std::string const & filename)
768  {
769  std::fstream outx( (mapfilename).c_str() , std::ios::binary | std::ios::out );
770 
771  float buff_f;
772  int buff_i;
773  float buff_vf[3];
774  int buff_vi[3];
775  int symBytes = 0;
776 
777  // extent
778  buff_vi[0] = nX_; buff_vi[1] = nY_; buff_vi[2] = nZ_;
779  outx.write(reinterpret_cast <char*>(buff_vi), sizeof(int)*3);
780 
781  // mode
782  buff_i = 2;
783  outx.write(reinterpret_cast <char*>(&buff_i), sizeof(int));
784 
785  // origin
786  buff_vi[0]= 0; buff_vi[1]=0;buff_vi[2]=0;
787  outx.write(reinterpret_cast <char*>(buff_vi), sizeof(int)*3);
788 
789  // grid
790  outx.write(reinterpret_cast <char*>(&grid[0]), sizeof(int)*3);
791 
792  // cell params
793  outx.write(reinterpret_cast <char*>(&cellDimensions), sizeof(float)*3);
794  outx.write(reinterpret_cast <char*>(&cellAngles), sizeof(float)*3);
795 
796  // crs2xyz
797  buff_vi[0] = 1; buff_vi[1] = 2; buff_vi[2] = 3;
798  outx.write(reinterpret_cast <char*>(buff_vi), sizeof(int)*3);
799 
800  // min, max, mean dens
801  buff_vf[0] = -100.0; buff_vf[1] = 100.0; buff_vf[2] = 0.0;
802  outx.write(reinterpret_cast <char*>(buff_vf), sizeof(float)*3);
803 
804  // 4 bytes junk
805  buff_i = 0;
806  outx.write(reinterpret_cast <char*>(&buff_i), sizeof(int));
807 
808  // symmops (to do!)
809  outx.write(reinterpret_cast <char*>(&symBytes), sizeof(int));
810 
811  // 112 bytes junk
812  buff_i = 0;
813  for (int i=0; i<28; ++i) {
814  outx.write(reinterpret_cast <char*>(&buff_i), sizeof(int));
815  }
816 
817  // Write "MAP" at byte 208, indicating a CCP4 file.
818  char buff_s[80]; strcpy(buff_s, "MAP DD");
819  outx.write(reinterpret_cast <char*>(buff_s), 8);
820 
821  // fill remainder of head with junk
822  int nJunkWords = (CCP4HDSIZE - 216) /4;
823  buff_i = 0;
824  for (int i=0; i<nJunkWords; ++i) {
825  outx.write(reinterpret_cast <char*>(&buff_i), sizeof(int));
826  }
827 
828  // data
829  int coord[3];
830  for (coord[2] = 1; coord[2] <= density.u3(); coord[2]++) {
831  for (coord[1] = 1; coord[1] <= density.u2(); coord[1]++) {
832  for (coord[0] = 1; coord[0] <= density.u1(); coord[0]++) {
833  buff_f = (float) density(coord[0],coord[1],coord[2]);
834  outx.write(reinterpret_cast <char*>(&buff_f), sizeof(float));
835  }
836  }
837  }
838  }
839 */
840 
841 private:
842  void setTop()
843  {
844  tX_ = bX_ + nX_*lX_;
845  tY_ = bY_ + nY_*lY_;
846  tZ_ = bZ_ + nZ_*lZ_;
847  }
848 
849  void setValue(int index, T value)
850  {
851  if (value == 0)
852  {
853  fullyOccupied_ = false;
854  }
855  assert( index >= 0 && index < npoints_ );
856  this->zones_[index] = value;
857  }
858 
859  T getValue(int index) const
860  {
861  if (index < 0 || index >= npoints_)
862  {
863  return -1;
864  } else
865  {
866  return this->zones_[index];
867  }
868  }
869 
870  int get_index(int ix, int iy, int iz) const
871  {
872  int index;
873  index = ix*(nY_*nZ_) + iy*(nZ_) + iz;
874  return index;
875  }
876 
877 
878 private:
879 
880  int nX_, nY_, nZ_;
885  int npoints_;
888 
889 };
890 
891 }
892 }
893 
894 
895 #endif /* GRID_HH_ */