diff --git a/DDCore/src/Segementations.cpp b/DDCore/src/Segmentations.cpp
similarity index 98%
rename from DDCore/src/Segementations.cpp
rename to DDCore/src/Segmentations.cpp
index de158701595ee88fe0ed919da75ade6d7e7d19c4..9399f3b62487da0241f6bc68dd4468861d998747 100644
--- a/DDCore/src/Segementations.cpp
+++ b/DDCore/src/Segmentations.cpp
@@ -22,7 +22,6 @@ using DD4hep::DDSegmentation::SegmentationParameter;
 /// Standard constructor
 Segmentation::Object::Object(BaseSegmentation* s)
   : magic(magic_word()), useForHitPosition(0), segmentation(s) {
-	cout << "Creating Object " << this << ", segmentation " << s << endl;
   InstanceCount::increment(this);
 }
 
diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp
index 59a7d57af51d03ced8acd7b654ad7f6bee7352f5..56adf568a13d62c47387cfed526a33e8057b8dae 100644
--- a/DDCore/src/plugins/Compact2Objects.cpp
+++ b/DDCore/src/plugins/Compact2Objects.cpp
@@ -450,7 +450,16 @@ template <> void Converter<Readout>::operator()(xml_h e) const {
       for (it = parameters.begin(); it != parameters.end(); ++it) {
         Segmentation::Parameter p = *it;
     	if (seg.hasAttr(Unicode(p->name()))) {
-    	  p->value() = seg.attr<double>(Unicode(p->name()));
+    	  string pType = p->type();
+    	  if (pType.compare("int") == 0) {
+    		p->setValue(_toString(seg.attr<int>(Unicode(p->name()))));
+    	  } else if (pType.compare("float") == 0) {
+    		p->setValue(_toString(seg.attr<float>(Unicode(p->name()))));
+    	  } else if (pType.compare("double") == 0) {
+      		p->setValue(_toString(seg.attr<double>(Unicode(p->name()))));
+      	  } else {
+      		p->setValue(seg.attr<string>(Unicode(p->name())));
+      	  }
         } else if (not p->isOptional()) {
     	  throw_print("FAILED to create segmentation: " + type + ". Missing mandatory parameter: " + p->name() + "!");
     	}
diff --git a/DDCore/src/plugins/LCDDConverter.cpp b/DDCore/src/plugins/LCDDConverter.cpp
index 141c115af5ea515ddfcb9fdcfc30c7a9e11d7dfc..db55f19e62d66e37df2bb5e765841555e3a80f1f 100644
--- a/DDCore/src/plugins/LCDDConverter.cpp
+++ b/DDCore/src/plugins/LCDDConverter.cpp
@@ -813,7 +813,16 @@ xml_h LCDDConverter::handleSegmentation(Segmentation seg) const {
         xml.setAttr(Unicode(v->name()), Unicode(val));
         continue;
       }
-      xml.setAttr(Unicode(v->name()), v->value());
+      // translate from TGeo units to Geant4 units if necessary
+      if (v->unitType() == DDSegmentation::SegmentationParameter::LengthUnit) {
+    	  double value = _toDouble(v->value()) * CM_2_MM;
+    	  xml.setAttr(Unicode(v->name()), value);
+      } else if (v->unitType() == DDSegmentation::SegmentationParameter::AngleUnit) {
+    	  double value = _toDouble(v->value()) * DEGREE_2_RAD;
+    	  xml.setAttr(Unicode(v->name()), value);
+      } else {
+    	  xml.setAttr(Unicode(v->name()), v->value());
+      }
     }
   }
   return xml;
diff --git a/DDSegmentation/include/DDSegmentation/Segmentation.h b/DDSegmentation/include/DDSegmentation/Segmentation.h
index f22fa5e3695add7531aa042aee2cbcd72080b975..37562a67235ace2be999778780595efbae66c38e 100644
--- a/DDSegmentation/include/DDSegmentation/Segmentation.h
+++ b/DDSegmentation/include/DDSegmentation/Segmentation.h
@@ -14,6 +14,7 @@
 
 #include <map>
 #include <utility>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -22,6 +23,11 @@ namespace DDSegmentation {
 
 typedef SegmentationParameter* Parameter;
 typedef std::vector<Parameter> Parameters;
+typedef TypedSegmentationParameter<int>* IntParameter;
+typedef TypedSegmentationParameter<float>* FloatParameter;
+typedef TypedSegmentationParameter<double>* DoubleParameter;
+typedef TypedSegmentationParameter<std::string>* StringParameter;
+typedef SegmentationParameter::UnitType UnitType;
 
 /// Useful typedefs to differentiate cell IDs and volume IDs
 typedef long long int CellID;
@@ -34,7 +40,7 @@ struct Position {
 			X(x), Y(y), Z(z) {
 	}
 	/// Constructor using a foreign vector class. Requires methods x(), y() and z()
-	template <typename T> Position(const T& v) {
+	template<typename T> Position(const T& v) {
 		X = v.x();
 		Y = v.y();
 		Z = v.Z();
@@ -65,6 +71,8 @@ public:
 	/// Determine the cell ID based on the position
 	virtual CellID cellID(const Position& localPosition, const Position& globalPosition,
 			const VolumeID& volumeID) const = 0;
+	/// Calculates the neighbours of the given cell ID and adds them to the list of neighbours
+	virtual void neighbours(const CellID& cellID, std::set<CellID>& neighbours) const;
 	/// Access the encoding string
 	virtual std::string fieldDescription() const {
 		return _decoder->fieldDescription();
@@ -101,9 +109,18 @@ public:
 protected:
 	/// Default constructor used by derived classes passing the encoding string
 	Segmentation(const std::string& cellEncoding = "");
+	/// Default constructor used by derived classes passing an existing decoder
+	Segmentation(BitField64* decoder);
 
 	/// Add a parameter to this segmentation. Used by derived classes to define their parameters
-	virtual void registerParameter(const std::string& name, const std::string& description, double& parameter, const double& defaultValue, bool isOptional = false);
+	template<typename TYPE> void registerParameter(const std::string& name, const std::string& description,
+			TYPE& parameter, const TYPE& defaultValue, UnitType unitType = SegmentationParameter::NoUnit, bool isOptional = false) {
+		_parameters[name] = new TypedSegmentationParameter<TYPE>(name, description, parameter, defaultValue, unitType, isOptional);
+	}
+	/// Add a cell identifier to this segmentation. Used by derived classes to define their required identifiers
+	void registerIdentifier(const std::string& name, const std::string& description, std::string& identifier,
+			const std::string& defaultValue);
+
 	/// Helper method to convert a bin number to a 1D position
 	static double binToPosition(CellID bin, double cellSize, double offset = 0.);
 	/// Helper method to convert a 1D position to a cell ID
@@ -121,6 +138,8 @@ protected:
 	std::string _description;
 	/// The parameters for this segmentation
 	std::map<std::string, Parameter> _parameters;
+	/// The indices used for the encoding
+	std::map<std::string, StringParameter> _indexIdentifiers;
 
 private:
 	/// No copy constructor allowed
diff --git a/DDSegmentation/include/DDSegmentation/SegmentationFactory.h b/DDSegmentation/include/DDSegmentation/SegmentationFactory.h
index 8991cba888f8fb348f3b6db7474f9607862fff72..8097c7e402d879876b20a493b07f874f9d3d72b1 100644
--- a/DDSegmentation/include/DDSegmentation/SegmentationFactory.h
+++ b/DDSegmentation/include/DDSegmentation/SegmentationFactory.h
@@ -31,7 +31,7 @@ public:
 	/// Destructor
 	virtual ~SegmentationCreatorBase() {};
 	/// Create a new object
-	virtual Segmentation* create() const = 0;
+	virtual Segmentation* create(const std::string& identifier) const = 0;
 };
 
 /// Concrete class to create segmentation objects. Every segmentation needs to instantiate a static instance of this.
@@ -42,7 +42,7 @@ public:
 	/// Destructor
 	virtual ~SegmentationCreator() {};
 	/// Create a new object of the given type.
-	Segmentation* create() const {return new TYPE("");};
+	Segmentation* create(const std::string& identifier) const {return new TYPE(identifier);};
 };
 
 /// Factory for creating segmentation objects by type name
@@ -53,7 +53,7 @@ public:
 	/// Access to the global factory instance
 	static SegmentationFactory* instance();
 	/// Create a new segmentation object with the given type name. Returns NULL if type name is unknown.
-	Segmentation* create(const std::string& name) const;
+	Segmentation* create(const std::string& name, const std::string& identifier = "") const;
 	/// Access to the list of registered segmentations
 	std::vector<std::string> registeredSegmentations() const;
 protected:
diff --git a/DDSegmentation/include/DDSegmentation/SegmentationParameter.h b/DDSegmentation/include/DDSegmentation/SegmentationParameter.h
index 6abf54375f7841dc33ee04a117a9cdf2f259bc53..099fbdf9269047d2805743b171a6e51cab20d25e 100644
--- a/DDSegmentation/include/DDSegmentation/SegmentationParameter.h
+++ b/DDSegmentation/include/DDSegmentation/SegmentationParameter.h
@@ -12,20 +12,51 @@
 
 #include <sstream>
 #include <string>
+#include <typeinfo>
 
 namespace DD4hep {
 namespace DDSegmentation {
 
+/// Helper class to extract type names
+template <typename TYPE> struct TypeName {
+	static const char* name() {
+		return typeid(TYPE).name();
+	}
+};
+
+/// Specialization for int type
+template <> struct TypeName<int> {
+	static const char* name() {
+		return "int";
+	}
+};
+
+/// Specialization for float type
+template <> struct TypeName<float> {
+	static const char* name() {
+		return "float";
+	}
+};
+
+/// Specialization for double type
+template <> struct TypeName<double> {
+	static const char* name() {
+		return "double";
+	}
+};
+
+/// Specialization for string type
+template <> struct TypeName<std::string> {
+	static const char* name() {
+		return "string";
+	}
+};
+
 /// Class to hold a segmentation parameter with its description
 class SegmentationParameter {
 public:
-	/// Default constructor
-	SegmentationParameter(const std::string& name, const std::string& description, double& parameter,
-			const double& defaultValue, bool isOptional = false) :
-			_name(name), _description(description), _value(parameter), _defaultValue(defaultValue), _isOptional(
-					isOptional) {
-		_value = defaultValue;
-	}
+	/// Defines the parameter unit type (useful to convert to default set of units)
+	enum UnitType {NoUnit, LengthUnit, AngleUnit};
 	/// Destructor
 	virtual ~SegmentationParameter() {
 	}
@@ -37,22 +68,18 @@ public:
 	const std::string& description() const {
 		return _description;
 	}
-	/// Access to the parameter value
-	double& value() {
-		return _value;
-	}
-	/// Access to the parameter value
-	double value() const {
-		return _value;
-	}
-	/// Set the parameter value
-	void setValue(const double& value) {
-		_value = value;
-	}
-	/// Access to the parameter default value
-	const double& defaultValue() const {
-		return _defaultValue;
+	/// Access to the unit type
+	UnitType unitType() const {
+		return _unitType;
 	}
+	/// Access to the parameter type
+	virtual std::string type() const = 0;
+	/// Access to the parameter value in string representation
+	virtual std::string value() const = 0;
+	/// Set the parameter value in string representation
+	virtual void setValue(const std::string& value) = 0;
+	/// Access to the parameter default value in string representation
+	virtual std::string defaultValue() const = 0;
 	/// Check if this parameter is optional
 	bool isOptional() const {
 		return _isOptional;
@@ -60,25 +87,82 @@ public:
 	/// Printable version
 	std::string toString() const {
 		std::stringstream s;
-		s << _name << " = " << _value;
+		s << _name << " = " << value();
 		if (not _description.empty()) {
 			s << " (" << _description << ")";
 		}
 		return s.str();
 	}
 protected:
+	/// Default constructor used by derived classes
+	SegmentationParameter(const std::string& name, const std::string& description, UnitType unitType = NoUnit, bool isOptional = false) :
+			_name(name), _description(description), _unitType(unitType), _isOptional(isOptional) {
+	}
 	/// The parameter name
 	std::string _name;
 	/// The parameter description
 	std::string _description;
-	/// The parameter value
-	double& _value;
-	/// The parameter default value
-	double _defaultValue;
+	/// The unit type
+	UnitType _unitType;
 	/// Store if parameter is optional
 	bool _isOptional;
 };
 
+template<typename TYPE> class TypedSegmentationParameter: public SegmentationParameter {
+public:
+	/// Default constructor
+	TypedSegmentationParameter(const std::string& name, const std::string& description, TYPE& value,
+			const TYPE& defaultValue, SegmentationParameter::UnitType unitType = SegmentationParameter::NoUnit, bool isOptional = false) :
+			SegmentationParameter(name, description, unitType, isOptional), _value(value), _defaultValue(defaultValue) {
+		_value = defaultValue;
+	}
+
+	/// Access to the parameter value
+	const TYPE& typedValue() const {
+		return _value;
+	}
+
+	/// Set the parameter value
+	void setTypedValue(const TYPE& value) {
+		_value = value;
+	}
+
+	/// Access to the parameter default value
+	const TYPE& typedDefaultValue() const {
+		return _defaultValue;
+	}
+
+	/// Access to the parameter type
+	std::string type() const {
+		return TypeName<TYPE>::name();
+	}
+
+	/// Access to the parameter value in string representation
+	std::string value() const {
+		std::stringstream s;
+		s << _value;
+		return s.str();
+	}
+
+	/// Set the parameter value in string representation
+	void setValue(const std::string& value) {
+		std::stringstream s;
+		s << value;
+		s >> _value;
+	}
+
+	/// Access to the parameter default value in string representation
+	std::string defaultValue() const {
+		std::stringstream s;
+		s << _defaultValue;
+		return s.str();
+	}
+
+protected:
+	TYPE& _value;
+	TYPE _defaultValue;
+};
+
 } /* namespace DDSegmentation */
 } /* namespace DD4hep */
 #endif /* DDSegmentation_SEGMENTATIONPARAMETER_H_ */
diff --git a/DDSegmentation/src/CartesianGridXY.cpp b/DDSegmentation/src/CartesianGridXY.cpp
index a345ada3f0b7a760a448bc7e7a131669bffc687b..fef07f52e5349b17b248ae54c265475f6312521d 100644
--- a/DDSegmentation/src/CartesianGridXY.cpp
+++ b/DDSegmentation/src/CartesianGridXY.cpp
@@ -20,12 +20,12 @@ CartesianGridXY::CartesianGridXY(const string& cellEncoding) :
 	_description = "Cartesian segmentation in the local XY-plane";
 
 	// register all necessary parameters
-	registerParameter("gridSizeX", "Cell size in X", _gridSizeX, 1.);
-	registerParameter("gridSizeY", "Cell size in Y", _gridSizeY, 1.);
-	registerParameter("offsetX", "Cell offset in X", _offsetX, 0., true);
-	registerParameter("offsetY", "Cell offset in Y", _offsetY, 0., true);
-	_xId = "x";
-	_yId = "y";
+	registerParameter("grid_size_x", "Cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit);
+	registerParameter("grid_size_y", "Cell size in Y", _gridSizeY, 1., SegmentationParameter::LengthUnit);
+	registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true);
+	registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true);
+	registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x");
+	registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y");
 }
 
 /// destructor
@@ -44,7 +44,7 @@ Position CartesianGridXY::position(const CellID& cellID) const {
 
 /// determine the cell ID based on the position
 CellID CartesianGridXY::cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const {
-	_decoder->reset();
+	_decoder->setValue(volumeID);
 	(*_decoder)[_xId] = positionToBin(localPosition.X, _gridSizeX, _offsetX);
 	(*_decoder)[_yId] = positionToBin(localPosition.Y, _gridSizeY, _offsetY);
 	return _decoder->getValue();
diff --git a/DDSegmentation/src/CartesianGridXYZ.cpp b/DDSegmentation/src/CartesianGridXYZ.cpp
index 52484839970226e506848a818fd488287b7d81b3..85b20c709c5d49bdc80be800641d416a7844c3c8 100644
--- a/DDSegmentation/src/CartesianGridXYZ.cpp
+++ b/DDSegmentation/src/CartesianGridXYZ.cpp
@@ -20,9 +20,9 @@ CartesianGridXYZ::CartesianGridXYZ(const string& cellEncoding) :
 	_description = "Cartesian segmentation in the local coordinates";
 
 	// register all necessary parameters
-	registerParameter("gridSizeZ", "Cell size in Z", _gridSizeZ, 1.);
-	registerParameter("offsetZ", "Cell offset in Z", _offsetZ, 0., true);
-	_zId = "z";
+	registerParameter("grid_size_z", "Cell size in Z", _gridSizeZ, 1., SegmentationParameter::LengthUnit);
+	registerParameter("offset_z", "Cell offset in Z", _offsetZ, 0., SegmentationParameter::LengthUnit, true);
+	registerIdentifier("identifier_z", "Cell ID identifier for Z", _zId, "z");
 }
 
 /// destructor
@@ -42,7 +42,7 @@ Position CartesianGridXYZ::position(const CellID& cellID) const {
 
 /// determine the cell ID based on the position
 CellID CartesianGridXYZ::cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const {
-	_decoder->reset();
+	_decoder->setValue(volumeID);
 	(*_decoder)[_xId] = positionToBin(localPosition.X, _gridSizeX, _offsetX);
 	(*_decoder)[_yId] = positionToBin(localPosition.Y, _gridSizeY, _offsetY);
 	(*_decoder)[_zId] = positionToBin(localPosition.Z, _gridSizeZ, _offsetZ);
diff --git a/DDSegmentation/src/CartesianGridXZ.cpp b/DDSegmentation/src/CartesianGridXZ.cpp
index 61ec209c1dafe80cef21d3a9131ef3e70a441841..4a5ef64f8f4e96c69fa8bd25c18534c158ee7ced 100644
--- a/DDSegmentation/src/CartesianGridXZ.cpp
+++ b/DDSegmentation/src/CartesianGridXZ.cpp
@@ -22,12 +22,12 @@ CartesianGridXZ::CartesianGridXZ(const string& cellEncoding) :
 	_description = "Cartesian segmentation in the local XY-plane";
 
 	// register all necessary parameters
-	registerParameter("gridSizeX", "Cell size in X", _gridSizeX, 1.);
-	registerParameter("gridSizeZ", "Cell size in Z", _gridSizeZ, 1.);
-	registerParameter("offsetX", "Cell offset in X", _offsetX, 0., true);
-	registerParameter("offsetZ", "Cell offset in Z", _offsetZ, 0., true);
-	_xId = "x";
-	_zId = "y";
+	registerParameter("grid_size_x", "Cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit);
+	registerParameter("grid_size_z", "Cell size in Z", _gridSizeZ, 1., SegmentationParameter::LengthUnit);
+	registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true);
+	registerParameter("offset_z", "Cell offset in Z", _offsetZ, 0., SegmentationParameter::LengthUnit, true);
+	registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x");
+	registerIdentifier("identifier_z", "Cell ID identifier for Z", _zId, "z");
 }
 
 /// destructor
@@ -47,7 +47,7 @@ Position CartesianGridXZ::position(const CellID& cellID) const {
 
 /// determine the cell ID based on the position
 CellID CartesianGridXZ::cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const {
-	_decoder->reset();
+	_decoder->setValue(volumeID);
 	(*_decoder)[_xId] = positionToBin(localPosition.X, _gridSizeX, _offsetX);
 	(*_decoder)[_zId] = positionToBin(localPosition.Z, _gridSizeZ, _offsetZ);
 	return _decoder->getValue();
diff --git a/DDSegmentation/src/ProjectiveCylinder.cpp b/DDSegmentation/src/ProjectiveCylinder.cpp
index 6793435a876190fb3311492985cf7bb20b5022ca..e06f6ee0bc9960d652a3bd3298b16370d31fcd2c 100644
--- a/DDSegmentation/src/ProjectiveCylinder.cpp
+++ b/DDSegmentation/src/ProjectiveCylinder.cpp
@@ -15,6 +15,8 @@ namespace DD4hep {
 namespace DDSegmentation {
 
 using std::string;
+using Util::thetaFromXYZ;
+using Util::phiFromXYZ;
 
 /// default constructor using an encoding string
 ProjectiveCylinder::ProjectiveCylinder(const string& cellEncoding) :
@@ -24,12 +26,12 @@ ProjectiveCylinder::ProjectiveCylinder(const string& cellEncoding) :
 	_description = "Projective segmentation in the global coordinates";
 
 	// register all necessary parameters
-	registerParameter("thetaBins", "Number of bins theta", _thetaBins, 1.);
-	registerParameter("phiBins", "Number of bins phi", _phiBins, 1.);
-	registerParameter("offsetTheta", "Angular offset in theta", _offsetTheta, 0., true);
-	registerParameter("offsetPhi", "Angular offset in phi", _offsetPhi, 0., true);
-	_thetaID = "theta";
-	_phiID = "phi";
+	registerParameter("theta_bins", "Number of bins theta", _thetaBins, 1.);
+	registerParameter("phi_bins", "Number of bins phi", _phiBins, 1.);
+	registerParameter("offset_theta", "Angular offset in theta", _offsetTheta, 0., SegmentationParameter::AngleUnit, true);
+	registerParameter("offset_phi", "Angular offset in phi", _offsetPhi, 0., SegmentationParameter::AngleUnit, true);
+	registerIdentifier("identifier_theta", "Cell ID identifier for theta", _thetaID, "theta");
+	registerIdentifier("identifier_phi", "Cell ID identifier for phi", _phiID, "phi");
 }
 
 /// destructor
@@ -44,8 +46,12 @@ Position ProjectiveCylinder::position(const long64& cellID) const {
 
 /// determine the cell ID based on the position
 CellID ProjectiveCylinder::cellID(const Position& localPosition, const Position& globalPosition, const VolumeID& volumeID) const {
-	// TODO
-	return 0;
+	_decoder->setValue(volumeID);
+	double theta = thetaFromXYZ(globalPosition);
+	double phi = phiFromXYZ(globalPosition);
+	(*_decoder)[_thetaID] = positionToBin(theta, M_PI / (double) _thetaBins, _offsetTheta);
+	(*_decoder)[_phiID] = positionToBin(phi, 2 * M_PI / (double) _phiBins, _offsetPhi);
+	return _decoder->getValue();
 }
 
 /// determine the polar angle theta based on the cell ID
diff --git a/DDSegmentation/src/Segmentation.cpp b/DDSegmentation/src/Segmentation.cpp
index 2a8333d60bfe1503a4f291b772e11d336f49fbcf..8b12a4c9edf9388e4dc6e8b537b7466c98e93caf 100644
--- a/DDSegmentation/src/Segmentation.cpp
+++ b/DDSegmentation/src/Segmentation.cpp
@@ -24,7 +24,12 @@ using std::vector;
 
 /// Default constructor used by derived classes passing the encoding string
 Segmentation::Segmentation(const string& cellEncoding) :
-	_name("Segmentation"), _type("Segmentation"), _decoder(new BitField64(cellEncoding)), _ownsDecoder(true) {
+		_name("Segmentation"), _type("Segmentation"), _decoder(new BitField64(cellEncoding)), _ownsDecoder(true) {
+}
+
+/// Default constructor used by derived classes passing an existing decoder
+Segmentation::Segmentation(BitField64* decoder) :
+		_name("Segmentation"), _type("Segmentation"), _decoder(decoder), _ownsDecoder(false) {
 }
 
 /// Destructor
@@ -42,10 +47,32 @@ Segmentation::~Segmentation() {
 	}
 }
 
+/// Calculates the neighbours of the given cell ID and adds them to the list of neighbours
+void Segmentation::neighbours(const CellID& cellID, std::set<CellID>& neighbours) const {
+	map<string, StringParameter>::const_iterator it;
+	for (it = _indexIdentifiers.begin(); it != _indexIdentifiers.end(); ++it) {
+		string identifier = it->second->typedValue();
+		_decoder->setValue(cellID);
+		int currentValue = (*_decoder)[identifier];
+		// add both neighbouring cell IDs, don't add out of bound indices
+		try {
+			(*_decoder)[identifier] = currentValue - 1;
+			neighbours.insert(_decoder->getValue());
+		} catch (runtime_error& e) {
+			// nothing to do
+		}
+		try {
+			(*_decoder)[identifier] = currentValue + 1;
+			neighbours.insert(_decoder->getValue());
+		} catch (runtime_error& e) {
+			// nothing to do
+		}
+	}
+}
+
 /// Set the underlying decoder
 void Segmentation::setDecoder(BitField64* decoder) {
 	if (_ownsDecoder and _decoder != 0) {
-		std::cout << _decoder << std::endl;
 		delete _decoder;
 	}
 	_decoder = decoder;
@@ -83,12 +110,15 @@ void Segmentation::setParameters(const Parameters& parameters) {
 	}
 }
 
-/// Add a parameter to this segmentation. Used by derived classes to define their parameters
-void Segmentation::registerParameter(const std::string& name, const std::string& description, double& parameter, const double& defaultValue, bool isOptional) {
-	_parameters[name] = new SegmentationParameter(name, description, parameter, defaultValue, isOptional);
+/// Add a cell identifier to this segmentation. Used by derived classes to define their required identifiers
+void Segmentation::registerIdentifier(const string& name, const string& description, string& identifier,
+		const string& defaultValue) {
+	StringParameter idParameter = new TypedSegmentationParameter<string>(name, description, identifier, defaultValue,
+			SegmentationParameter::NoUnit, true);
+	_parameters[name] = idParameter;
+	_indexIdentifiers[name] = idParameter;
 }
 
-
 /// Helper method to convert a bin number to a 1D position
 double Segmentation::binToPosition(long64 bin, double cellSize, double offset) {
 	return bin * cellSize + offset;
@@ -99,7 +129,7 @@ int Segmentation::positionToBin(double position, double cellSize, double offset)
 	if (cellSize == 0.) {
 		throw runtime_error("Invalid cell size: 0.0");
 	}
-	return int((position + 0.5 * cellSize - offset)/cellSize);
+	return int((position + 0.5 * cellSize - offset) / cellSize);
 }
 
 } /* namespace DDSegmentation */
diff --git a/DDSegmentation/src/SegmentationFactory.cpp b/DDSegmentation/src/SegmentationFactory.cpp
index 491527e610d5cf9457e8532e7a0b7d4f8b3e5f9c..8ce2cb994db2506382ef07dea7fb8fad2079082c 100644
--- a/DDSegmentation/src/SegmentationFactory.cpp
+++ b/DDSegmentation/src/SegmentationFactory.cpp
@@ -31,11 +31,11 @@ SegmentationFactory* SegmentationFactory::instance() {
 }
 
 /// Create a new segmentation object with the given type name. Returns NULL if type name is unknown.
-Segmentation* SegmentationFactory::create(const string& name) const {
+Segmentation* SegmentationFactory::create(const string& name, const string& identifier) const {
 	map<string, SegmentationCreatorBase*>::const_iterator it;
 	it = _segmentations.find(name);
 	if (it != _segmentations.end()) {
-		return it->second->create();
+		return it->second->create(identifier);
 	}
 	return 0;
 }
diff --git a/examples/CLICSiD/compact/BarrelCalorimeter.xml b/examples/CLICSiD/compact/BarrelCalorimeter.xml
index 88f952b7e2d02236a62c0a06c6a9f95ae4a95006..d61c1c088ba140342f107a8b0a538672dbaa23de 100644
--- a/examples/CLICSiD/compact/BarrelCalorimeter.xml
+++ b/examples/CLICSiD/compact/BarrelCalorimeter.xml
@@ -396,7 +396,7 @@
     <readouts>
 
         <readout name="MuonBarrelHits">
-            <segmentation type="CartesianGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
+            <segmentation type="CartesianGridXY" grid_size_x="3.0*cm" grid_size_y="3.0*cm" />
             <id>system:8,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
         </readout>
 <!--
diff --git a/examples/ILDExDet/compact/ILDEx.xml b/examples/ILDExDet/compact/ILDEx.xml
index d5814b8b7ad52c45be9a834f8ea7382dc0b3f6fa..bc191d450a99a56fa5e31a5d921a049a4573f896 100644
--- a/examples/ILDExDet/compact/ILDEx.xml
+++ b/examples/ILDExDet/compact/ILDEx.xml
@@ -253,11 +253,11 @@
         </readout>
 
         <readout name="HcalBarrelHits">
-            <segmentation type="RegularNgonCartesianGridXY" gridSizeY="30.0*mm" gridSizeZ="30.0*mm" />
+            <segmentation type="CartesianGridXZ" grid_size_x="30.0*mm" grid_size_z="30.0*mm" />
             <id>system:6,stave:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
         </readout>
         <readout name="HcalEndcapHits">
-            <segmentation type="GlobalGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" />
+            <segmentation type="CartesianGridXY" grid_size_x="3.0*cm" grid_size_y="3.0*cm" />
             <id>system:6,stave:1,module:1,endcapID:5,layer:8,slice:5,x:32:-16,y:-16</id>
         </readout>
 
diff --git a/examples/Segmentation/SegmentationTest.cpp b/examples/Segmentation/SegmentationTest.cpp
index 238c30dfe6b49f57c08e17384a9edcbd3fcb309c..3452dbffaeb6307f878f57a8159e8399f429d35c 100644
--- a/examples/Segmentation/SegmentationTest.cpp
+++ b/examples/Segmentation/SegmentationTest.cpp
@@ -10,6 +10,8 @@
 #include "DDSegmentation/SegmentationFactory.h"
 #include "DDSegmentation/SegmentationParameter.h"
 
+#include <set>
+
 using namespace std;
 using namespace DD4hep;
 using namespace Geometry;
@@ -29,8 +31,29 @@ int main(int argc, char** argv) {
 		Parameters parameters = s->parameters();
 		Parameters::iterator it;
 		for (it = parameters.begin(); it != parameters.end(); ++it) {
-			cout << "\t\t" << it->first << " = " << it->second << endl;
+			Parameter p = *it;
+			cout << "\t\t" << p->name() << " = " << p->value() << endl;
 		}
+		delete s;
+	}
+
+	DDSegmentation::Segmentation* s = f->create("CartesianGridXY", "system:8,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16");
+	BitField64& d = *s->decoder();
+	d["system"] = 1;
+	d["barrel"] = 0;
+	d["module"] = 5;
+	d["layer"] = 12;
+	d["x"] = 10;
+	d["y"] = -30;
+	cout << "Neighbours of " << d.valueString() << ": "<< endl;
+	CellID id = d.getValue();
+	set<CellID> neighbours;
+	s->neighbours(id, neighbours);
+	set<CellID>::iterator itNeighbour;
+	for (itNeighbour = neighbours.begin(); itNeighbour != neighbours.end(); ++itNeighbour) {
+		d.setValue(*itNeighbour);
+		cout << "\t" << d.valueString() << std::endl;
 	}
+	delete s;
 	return 0;
 };
diff --git a/examples/noviceN04/compact/N04.xml b/examples/noviceN04/compact/N04.xml
index f15577b8ffca2570b17b9e706e4b4124ff16a027..655e14945f830f49ca46978d818716032cda4fac 100644
--- a/examples/noviceN04/compact/N04.xml
+++ b/examples/noviceN04/compact/N04.xml
@@ -170,13 +170,13 @@
     </readout>
 
     <readout name="CalorimeterCollection">
-      <segmentation type="RegularNgonCartesianGridXY" gridSizeY="30.0*mm" gridSizeZ="30.0*mm" />
+      <segmentation type="CartesianGridXZ" grid_size_x="30.0*mm" grid_size_z="30.0*mm" />
       <!--FIXME: should actually be (seg faults):  segmentation type="NonProjectiveCylinder" gridSizePhi="caloCell_dphi" gridSizeZ="caloRing_dz" /-->
       <id>system:6,stave:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
     </readout>
 
     <readout name="MuonCollection">
-      <segmentation type="RegularNgonCartesianGridXY" gridSizeY="30.0*mm" gridSizeZ="30.0*mm" />
+      <segmentation type="CartesianGridXZ" grid_size_x="30.0*mm" grid_size_z="30.0*mm" />
       <!--FIXME: should actually be (seg faults):  segmentation type="ProjectiveCylinder" gridSizeY="30.0*mm" gridSizeZ="30.0*mm" /-->
       <id>system:6,stave:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id>
     </readout>