Index: kernel/include/base_types.h
===================================================================
--- kernel/include/base_types.h	(revision 855)
+++ kernel/include/base_types.h	(working copy)
@@ -49,27 +49,22 @@
 struct ScoreStateTag {};
 struct OptimizerStateTag {};
 
-typedef Index<ParticleTag> ParticleIndex;
 typedef Index<RestraintTag> RestraintIndex;
 typedef Index<ScoreStateTag> ScoreStateIndex;
 typedef Index<OptimizerStateTag> OptimizerStateIndex;
+typedef Index<ParticleTag> ParticleIndex;
+typedef std::vector<ParticleIndex> ParticleIndexes;
 
+/* This needs to be here so that both Model and Particle can use Particles */
 class Particle;
 //! A class which is used for representing collections of particles
 /**
-   We need this to have a uniform return type for python.
-   \todo It would be nice to use internal::Vector instead, but that
-   is not as pretty for Python.
+ We need this to have a uniform return type for python.
+ \todo It would be nice to use internal::Vector instead, but that
+ is not as pretty for Python.
  */
 typedef std::vector<Particle*> Particles;
-typedef std::pair<Particle*, Particle*> ParticlePair;
-typedef std::vector<ParticlePair> ParticlePairs;
 
-
-typedef std::vector<ParticleIndex> ParticleIndexes;
-
-class Particle;
-
 //! The type used to identify float attributes in the Particles
 IMP_DECLARE_KEY_TYPE(FloatKey, 0);
 //! The type used to identify int attributes in the Particles
Index: kernel/include/Model.h
===================================================================
--- kernel/include/Model.h	(revision 855)
+++ kernel/include/Model.h	(working copy)
@@ -11,7 +11,9 @@
 
 #include "IMP_config.h"
 #include "Object.h"
+#include "Particle.h"
 #include "internal/kernel_version_info.h"
+#include "container_macros.h"
 #include "base_types.h"
 #include "VersionInfo.h"
 
Index: kernel/include/SConscript
===================================================================
--- kernel/include/SConscript	(revision 855)
+++ kernel/include/SConscript	(working copy)
@@ -7,7 +7,8 @@
          'DecoratorBase.h', 'Vector3D.h',
          'UnaryFunction.h', 'PairScore.h', 'SingletonScore.h', 'macros.h',
          'TripletScore.h', 'exception.h', 'VersionInfo.h',
-         'Object.h', 'Pointer.h', 'RefCountedObject.h', 'ParticleRefiner.h']
+         'Object.h', 'Pointer.h', 'RefCountedObject.h', 'ParticleRefiner.h',
+         'container_macros.h']
 
 # Subdirectories
 files = [File(f) for f in files] \
Index: kernel/include/Particle.h
===================================================================
--- kernel/include/Particle.h	(revision 855)
+++ kernel/include/Particle.h	(working copy)
@@ -629,6 +629,87 @@
   particles_.remove(name);
 }
 
+
+//! A class to store a pair of particles.
+/** \note These do not due ref counting currently. SWIG prevents
+    use of Pointer<Particle> as the storage type without some
+    gynmastics.
+ */
+class ParticlePair {
+  bool is_default() const {return false;}
+public:
+  typedef ParticlePair This;
+  Particle *first, *second;
+  ParticlePair(): first(NULL), second(NULL){}
+  ParticlePair(Particle *a, Particle *b):
+  first(a), second(b) {}
+  IMP_COMPARISONS_2(first, second)
+  Particle * operator[](unsigned int i) const {
+    switch (i) {
+      case 0:
+        return first;
+      case 1:
+        return second;
+      default:
+        throw IndexException("Invalid member of pair");
+    }
+  }
+  Particle *& operator[](unsigned int i) {
+    switch (i) {
+      case 0:
+        return first;
+      case 1:
+        return second;
+      default:
+        throw IndexException("Invalid member of pair");
+    }
+  }
+  
+};
+
+typedef std::vector<ParticlePair> ParticlePairs;
+
+
+
+//! Store three particles
+class ParticleTriplet {
+  bool is_default() const {return false;}
+public:
+  typedef ParticleTriplet This;
+  Particle *first, *second, *third;
+  ParticleTriplet(): first(NULL), second(NULL), third(NULL){}
+  ParticleTriplet(Particle *a, Particle *b, Particle *c):
+  first(a), second(b), third(c) {}
+  IMP_COMPARISONS_3(first, second, third)
+  Particle *operator[](unsigned int i) const {
+    switch (i) {
+      case 0:
+        return first;
+      case 1:
+        return second;
+      case 2:
+        return third;
+      default:
+        throw IndexException("Invalid member of triplet");
+    };
+  }
+  Particle *&operator[](unsigned int i) {
+    switch (i) {
+      case 0:
+        return first;
+      case 1:
+        return second;
+      case 2:
+        return third;
+      default:
+        throw IndexException("Invalid member of triplet");
+    };
+  }
+  
+};
+
+typedef std::vector<ParticleTriplet> ParticleTriplets;
+
 IMP_END_NAMESPACE
 
 #endif  /* IMP_PARTICLE_H */
Index: kernel/include/Object.h
===================================================================
--- kernel/include/Object.h	(revision 855)
+++ kernel/include/Object.h	(working copy)
@@ -63,4 +63,11 @@
 
 IMP_END_NAMESPACE
 
+//! Call the assert_is_valid method in the object base
+#define IMP_CHECK_OBJECT(obj) do {              \
+IMP_assert(obj != NULL, "NULL object");     \
+(obj)->assert_is_valid();                   \
+} while (false)
+
+
 #endif  /* IMP_OBJECT_H */
Index: kernel/include/Restraint.h
===================================================================
--- kernel/include/Restraint.h	(revision 855)
+++ kernel/include/Restraint.h	(working copy)
@@ -17,6 +17,7 @@
 #include "Pointer.h"
 #include "log.h"
 #include "utility.h"
+#include "container_macros.h"
 
 #include <vector>
 #include <iostream>
Index: kernel/include/ParticleRefiner.h
===================================================================
--- kernel/include/ParticleRefiner.h	(revision 855)
+++ kernel/include/ParticleRefiner.h	(working copy)
@@ -9,6 +9,7 @@
 
 #include "IMP_config.h"
 #include "base_types.h"
+#include "Particle.h"
 #include "VersionInfo.h"
 #include "RefCountedObject.h"
 
Index: kernel/include/macros.h
===================================================================
--- kernel/include/macros.h	(revision 855)
+++ kernel/include/macros.h	(working copy)
@@ -247,194 +247,4 @@
 #define IMP_COPY_CONSTRUCTOR(TC) TC(const TC &o){copy_from(o);}  \
   TC& operator=(const TC &o) {copy_from(o); return *this;}
 
-
-
-
-/** \internal
- */
-#define IMP_CONTAINER_CORE(protection, Ucname, lcname, Data, IndexType,\
-                           Container)                                  \
-  protection:                                                          \
-  /** \short Add an object.
-      \param[in] obj Pointer to the object
-      \return index of object within the object
-  */                                                                    \
-  IndexType add_##lcname(Data obj);                                     \
-  /** \short Add several objects.
-      \param[in] obj a vector of pointers
-  */                                                                    \
-  void add_##lcname##s(const std::vector<Data>& obj);                   \
-  /** \short Clear the contents of the container */                     \
-  void clear_##lcname##s();                                             \
-  /** \short return the number of objects*/                             \
-  unsigned int get_number_of_##lcname##s() const {                          \
-    return lcname##_vector_.size();}                                    \
-  /** \short Get object refered to by the index
-      \throws IndexException if the index is out of range
-   */                                                                   \
-  Data get_##lcname(IndexType i) const {                                \
-    return lcname##_vector_[i];                                         \
-  }                                                                     \
-  /** \short An iterator through the objects.
-      The value type is a pointer.*/                                     \
-  typedef Container::iterator Ucname##Iterator;                          \
-  /** \short A const iterator through the objects.
-      The value type is a pointer.*/                                     \
-  typedef Container::const_iterator Ucname##ConstIterator;               \
-  Ucname##Iterator lcname##s_begin() {return lcname##_vector_.begin();}  \
-  Ucname##Iterator lcname##s_end() {return lcname##_vector_.end();}      \
-  Ucname##ConstIterator lcname##s_begin() const {                        \
-    return lcname##_vector_.begin();}                                    \
-  Ucname##ConstIterator lcname##s_end() const {                          \
-    return lcname##_vector_.end();}                                      \
- private:                                                                \
-  /** \internal */                                                       \
-  Container lcname##_vector_;                                            \
- protection:
-
-/** \internal
- */
-#define IMP_CONTAINER_CORE_IMPL(Class, Ucname, lcname, Data, IndexType, \
-                                Init_obj, Onchanged)                    \
-  IndexType Class::add_##lcname(Data obj) {                             \
-    IndexType index= lcname##_vector_.push_back(obj);                   \
-    Init_obj;                                                           \
-    Onchanged;                                                          \
-    if (false) {index=index; obj=obj;};                                 \
-    return index;                                                       \
-  }                                                                     \
-  void Class::add_##lcname##s(const std::vector<Data> &objs) {          \
-    unsigned int osz= lcname##_vector_.size();                          \
-    lcname##_vector_.insert(lcname##_vector_.end(), objs.begin(),       \
-                            objs.end());                                \
-    for (unsigned int i=0; i< objs.size(); ++i) {                       \
-      Data obj= lcname##_vector_[osz+i];                                \
-      IndexType index(osz+i);                                           \
-      Init_obj;                                                         \
-      if (false) {obj=obj; index=index;}                                \
-    }                                                                   \
-    Onchanged;                                                          \
-  }                                                                     \
-  /** \short Clear the contents of the container */                     \
-  void Class::clear_##lcname##s(){                                      \
-    lcname##_vector_.clear();                                           \
-    Onchanged;                                                          \
-  }                                                                     \
-
-
-//! Use this to add a container of IMP objects
-/**
-   Such a container adds public methods add_foo, get_foo, get_number_of_foo
-   and a private type foo_iterator, with methods foo_begin, foo_end.
-   \param[in] protection The level of protection for the container.
-   \param[in] Ucname The name of the type in uppercase
-   \param[in] lcname The name of the type in lower case
-   \param[in] Data The type of the data to store.
-
-   \note the type Ucnames must be declared and be a vector of
-   Data.
- */
-#define IMP_LIST(protection, Ucname, lcname, Data)                      \
-  protection:                                                           \
-  /** \short Remove any occurences of d from the container */           \
-  void erase_##lcname(Data d);                                          \
-  /** \short Get a container of all the objects.
-     This is for Python as the container can be used like a Python list*/\
-  const Ucname##s &get_##lcname##s() const {                             \
-    return static_cast< const Ucname##s &>(lcname##_vector_);           \
-  }                                                                     \
-  void set_##lcname##s(const Ucname##s &ps) {                           \
-    clear_##lcname##s();                                                \
-    add_##lcname##s(ps);                                                \
-  }                                                                     \
-  IMP_CONTAINER_CORE(protection, Ucname, lcname, Data, unsigned int,    \
-                     IMP::internal::Vector<Data>)
-
-
-
-//! Use this to add a container of IMP objects
-/**
-   This code should go in a .cpp file. One macro for each IMP_CONTAINER.
-   \param[in] init Code to modify the passed in object. The object is obj
-   its index index.
-   \param[in] OnChanged Code to get executed when the container changes.
- */
-#define IMP_LIST_IMPL(Class, Ucname, lcname, Data, init, OnChanged)     \
-  IMP_CONTAINER_CORE_IMPL(Class, Ucname, lcname, Data, unsigned int,    \
-                          init, OnChanged)                              \
- /** \short Remove any occurences of d from the container */           \
-  void Class::erase_##lcname(Data d) {                                  \
-    for (Ucname##Iterator it= lcname##s_begin();                        \
-         it != lcname##s_end(); ++it) {                                 \
-      if (*it == d) {                                                   \
-        lcname##_vector_.erase(it); break;                              \
-      }                                                                 \
-    }                                                                   \
-    OnChanged;                                                          \
-  }                                                                     \
-
-
-
-//! Use this to add a set of IMP objects owned by the containing one
-/**
-   Such a container adds public methods add_foo, get_foo, get_number_of_foo
-   and a private type foo_iterator, with methods foo_begin, foo_end.
-   \param[in] Ucname The name of the type in uppercase
-   \param[in] lcname The name of the type in lower case
-   \param[in] IndexType The type to use for the index. This should be
-   an instantiation of Index<T> or something similar.
-
-   \note The type Ucnames must be declared and be a vector of
-   Data.
-   \note these containers are always public
-*/
-#define IMP_CONTAINER(Ucname, lcname, IndexType)            \
-  public:                                                   \
-  void remove_##lcname(IndexType i) ;                       \
-private:                                                                \
-/** \internal
-    This is an implementation detail.*/                                 \
-typedef IMP::internal::ObjectContainer<Ucname, IndexType>               \
-Ucname##Container;                                                      \
-IMP_CONTAINER_CORE(public, Ucname, lcname, Ucname*, IndexType,          \
-                   Ucname##Container)
-
-
-
-//! Use this to add a container of IMP objects
-/**
-   This code should go in a .cpp file. One macro for each
-   IMP_CONTAINER.
-   \param[in] init Code to modify the passed in object. The object is obj
-   its index index.
-   \param[in] onchanged Code to execute when the container is changed.
-   \param[in] onremove Code to execute when an object is removed. The object
-   being removed is obj.
- */
-#define IMP_CONTAINER_IMPL(Class, Ucname, lcname, IndexType, init,      \
-onchanged, onremove)                                                    \
-  void Class::remove_##lcname(IndexType i) {                            \
-    Ucname* obj= lcname##_vector_[i];                                   \
-    onremove;                                                           \
-    lcname##_vector_.remove(i);                                         \
-    if (false) std::cout << *obj;                                       \
-  }                                                                     \
-  IMP_CONTAINER_CORE_IMPL(Class, Ucname, lcname, Ucname*, IndexType,    \
-                          init,onchanged)
-
-
-
-//! Call the assert_is_valid method in the object base
-#define IMP_CHECK_OBJECT(obj) do {              \
-    IMP_assert(obj != NULL, "NULL object");     \
-    (obj)->assert_is_valid();                   \
-  } while (false)
-
-
-// They use IMP_CHECK_OBJECT and so must be included at the end
-
-#include "internal/Vector.h"
-#include "internal/ObjectContainer.h"
-
-
 #endif  /* IMP_MACROS_H */
Index: kernel/include/internal/ExponentialNumber.h
===================================================================
--- kernel/include/internal/ExponentialNumber.h	(revision 855)
+++ kernel/include/internal/ExponentialNumber.h	(working copy)
@@ -10,6 +10,7 @@
 #define IMP_EXPONENTIAL_NUMBER_H
 
 #include "../macros.h"
+#include "../base_types.h"
 
 #include <iostream>
 #include <cmath>
Index: kernel/include/container_macros.h
===================================================================
--- kernel/include/container_macros.h	(revision 0)
+++ kernel/include/container_macros.h	(revision 0)
@@ -0,0 +1,188 @@
+/*
+ *  \file container_macros.h
+ *  \brief Macros to define containers of objects
+ *
+ *  Copyright 2007-8 Sali Lab. All rights reserved.
+ *
+ */
+
+#ifndef IMP_INTERNAL_CONTAINER_MACROS_H
+#define IMP_INTERNAL_CONTAINER_MACROS_H
+
+#include "internal/Vector.h"
+#include "internal/ObjectContainer.h"
+#include "macros.h"
+
+/** \internal
+ */
+#define IMP_CONTAINER_CORE(protection, Ucname, lcname, Data, IndexType,\
+Container)                                  \
+protection:                                                          \
+/** \short Add an object.
+\param[in] obj Pointer to the object
+\return index of object within the object
+*/                                                                    \
+IndexType add_##lcname(Data obj);                                     \
+/** \short Add several objects.
+\param[in] obj a vector of pointers
+*/                                                                    \
+void add_##lcname##s(const std::vector<Data>& obj);                   \
+/** \short Clear the contents of the container */                     \
+void clear_##lcname##s();                                             \
+/** \short return the number of objects*/                             \
+unsigned int get_number_of_##lcname##s() const {                          \
+return lcname##_vector_.size();}                                    \
+/** \short Get object refered to by the index
+\throws IndexException if the index is out of range
+*/                                                                   \
+Data get_##lcname(IndexType i) const {                                \
+return lcname##_vector_[i];                                         \
+}                                                                     \
+/** \short An iterator through the objects.
+The value type is a pointer.*/                                     \
+typedef Container::iterator Ucname##Iterator;                          \
+/** \short A const iterator through the objects.
+The value type is a pointer.*/                                     \
+typedef Container::const_iterator Ucname##ConstIterator;               \
+Ucname##Iterator lcname##s_begin() {return lcname##_vector_.begin();}  \
+Ucname##Iterator lcname##s_end() {return lcname##_vector_.end();}      \
+Ucname##ConstIterator lcname##s_begin() const {                        \
+return lcname##_vector_.begin();}                                    \
+Ucname##ConstIterator lcname##s_end() const {                          \
+return lcname##_vector_.end();}                                      \
+private:                                                                \
+/** \internal */                                                       \
+Container lcname##_vector_;                                            \
+protection:
+
+/** \internal
+ */
+#define IMP_CONTAINER_CORE_IMPL(Class, Ucname, lcname, Data, IndexType, \
+Init_obj, Onchanged)                    \
+IndexType Class::add_##lcname(Data obj) {                             \
+IndexType index= lcname##_vector_.push_back(obj);                   \
+Init_obj;                                                           \
+Onchanged;                                                          \
+if (false) {index=index; obj=obj;};                                 \
+return index;                                                       \
+}                                                                     \
+void Class::add_##lcname##s(const std::vector<Data> &objs) {          \
+unsigned int osz= lcname##_vector_.size();                          \
+lcname##_vector_.insert(lcname##_vector_.end(), objs.begin(),       \
+objs.end());                                \
+for (unsigned int i=0; i< objs.size(); ++i) {                       \
+Data obj= lcname##_vector_[osz+i];                                \
+IndexType index(osz+i);                                           \
+Init_obj;                                                         \
+if (false) {obj=obj; index=index;}                                \
+}                                                                   \
+Onchanged;                                                          \
+}                                                                     \
+/** \short Clear the contents of the container */                     \
+void Class::clear_##lcname##s(){                                      \
+lcname##_vector_.clear();                                           \
+Onchanged;                                                          \
+}                                                                     \
+
+
+//! Use this to add a container of IMP objects
+/**
+ Such a container adds public methods add_foo, get_foo, get_number_of_foo
+ and a private type foo_iterator, with methods foo_begin, foo_end.
+ \param[in] protection The level of protection for the container.
+ \param[in] Ucname The name of the type in uppercase
+ \param[in] lcname The name of the type in lower case
+ \param[in] Data The type of the data to store.
+ 
+ \note the type Ucnames must be declared and be a vector of
+ Data.
+ */
+#define IMP_LIST(protection, Ucname, lcname, Data)                      \
+protection:                                                           \
+/** \short Remove any occurences of d from the container */           \
+void erase_##lcname(Data d);                                          \
+/** \short Get a container of all the objects.
+This is for Python as the container can be used like a Python list*/\
+const Ucname##s &get_##lcname##s() const {                             \
+return static_cast< const Ucname##s &>(lcname##_vector_);           \
+}                                                                     \
+void set_##lcname##s(const Ucname##s &ps) {                           \
+clear_##lcname##s();                                                \
+add_##lcname##s(ps);                                                \
+}                                                                     \
+IMP_CONTAINER_CORE(protection, Ucname, lcname, Data, unsigned int,    \
+IMP::internal::Vector<Data>)
+
+
+
+//! Use this to add a container of IMP objects
+/**
+ This code should go in a .cpp file. One macro for each IMP_CONTAINER.
+ \param[in] init Code to modify the passed in object. The object is obj
+ its index index.
+ \param[in] OnChanged Code to get executed when the container changes.
+ */
+#define IMP_LIST_IMPL(Class, Ucname, lcname, Data, init, OnChanged)     \
+IMP_CONTAINER_CORE_IMPL(Class, Ucname, lcname, Data, unsigned int,    \
+init, OnChanged)                              \
+/** \short Remove any occurences of d from the container */           \
+void Class::erase_##lcname(Data d) {                                  \
+for (Ucname##Iterator it= lcname##s_begin();                        \
+it != lcname##s_end(); ++it) {                                 \
+if (*it == d) {                                                   \
+lcname##_vector_.erase(it); break;                              \
+}                                                                 \
+}                                                                   \
+OnChanged;                                                          \
+}                                                                     \
+
+
+
+//! Use this to add a set of IMP objects owned by the containing one
+/**
+ Such a container adds public methods add_foo, get_foo, get_number_of_foo
+ and a private type foo_iterator, with methods foo_begin, foo_end.
+ \param[in] Ucname The name of the type in uppercase
+ \param[in] lcname The name of the type in lower case
+ \param[in] IndexType The type to use for the index. This should be
+ an instantiation of Index<T> or something similar.
+ 
+ \note The type Ucnames must be declared and be a vector of
+ Data.
+ \note these containers are always public
+ */
+#define IMP_CONTAINER(Ucname, lcname, IndexType)            \
+public:                                                   \
+void remove_##lcname(IndexType i) ;                       \
+private:                                                                \
+/** \internal
+This is an implementation detail.*/                                 \
+typedef IMP::internal::ObjectContainer<Ucname, IndexType>               \
+Ucname##Container;                                                      \
+IMP_CONTAINER_CORE(public, Ucname, lcname, Ucname*, IndexType,          \
+Ucname##Container)
+
+
+
+//! Use this to add a container of IMP objects
+/**
+ This code should go in a .cpp file. One macro for each
+ IMP_CONTAINER.
+ \param[in] init Code to modify the passed in object. The object is obj
+ its index index.
+ \param[in] onchanged Code to execute when the container is changed.
+ \param[in] onremove Code to execute when an object is removed. The object
+ being removed is obj.
+ */
+#define IMP_CONTAINER_IMPL(Class, Ucname, lcname, IndexType, init,      \
+onchanged, onremove)                                                    \
+void Class::remove_##lcname(IndexType i) {                            \
+Ucname* obj= lcname##_vector_[i];                                   \
+onremove;                                                           \
+lcname##_vector_.remove(i);                                         \
+if (false) std::cout << *obj;                                       \
+}                                                                     \
+IMP_CONTAINER_CORE_IMPL(Class, Ucname, lcname, Ucname*, IndexType,    \
+init,onchanged)
+
+#endif

Property changes on: kernel/include/container_macros.h
___________________________________________________________________
Added: svn:mergeinfo

Index: kernel/pyext/IMP_macros.i
===================================================================
--- kernel/pyext/IMP_macros.i	(revision 855)
+++ kernel/pyext/IMP_macros.i	(working copy)
@@ -53,3 +53,4 @@
 %enddef
 
 %include "IMP/macros.h"
+%include "IMP/container_macros.h"
Index: kernel/pyext/IMP.i
===================================================================
--- kernel/pyext/IMP.i	(revision 855)
+++ kernel/pyext/IMP.i	(working copy)
@@ -15,6 +15,31 @@
 
 %include "typemaps.i"
 
+%ignore IMP::ParticlePair::operator[];
+%ignore IMP::ParticleTriplet::operator[];
+%extend IMP::ParticlePair {
+  Particle* __getitem__(unsigned int index) const {
+    return self->operator[](index);
+  }
+  void __setitem__(unsigned int index, Particle* val) {
+    self->operator[](index) = val;
+  }
+  int __len__() const {
+      return 2;
+  }
+}
+%extend IMP::ParticleTriplet {
+  Particle* __getitem__(unsigned int index) const {
+    return self->operator[](index);
+  }
+  void __setitem__(unsigned int index, Particle* val) {
+    self->operator[](index) = val;
+  }
+  int __len__() const {
+      return 3;
+  }
+}  
+
 namespace IMP {
   %typemap(out) std::pair<Float,Float> {
      PyObject *tup= PyTuple_New(2);
@@ -124,8 +149,8 @@
   %template(OptimizerStateIndex) Index<OptimizerStateTag>;
   %template(Particles) ::std::vector<Particle*>;
   %template(ParticlesList) ::std::vector<Particles>;
-  %template(ParticlePair) ::std::pair<IMP::Particle*, IMP::Particle*>;
   %template(ParticlePairs) ::std::vector<ParticlePair>;
+  %template(ParticleTriplets) ::std::vector<ParticleTriplet>;
   %template(Restraints) ::std::vector<IMP::Restraint*>;
   %template(ScoreStates) ::std::vector<ScoreState*>;
   %template(OptimizerStates) ::std::vector<OptimizerState*>;