diff --git a/gstlal-inspiral/python/snglinspiraltable.c b/gstlal-inspiral/python/snglinspiraltable.c
index 44152ad925b36d33ac6a5b1a7dd5c96c169d9bec..96c4b512b6dc2c294923f170cfa00c1b86060d81 100644
--- a/gstlal-inspiral/python/snglinspiraltable.c
+++ b/gstlal-inspiral/python/snglinspiraltable.c
@@ -32,6 +32,7 @@
 #include <Python.h>
 #include <numpy/ndarrayobject.h>
 #include <structmember.h>
+#include <lal/Date.h>
 #include <lal/TimeSeries.h>
 #include <lal/Units.h>
 
@@ -39,6 +40,9 @@
 #include <snglinspiralrowtype.h>
 
 
+static PyObject *LIGOTimeGPSType = NULL;
+
+
 /*
  * ============================================================================
  *
@@ -165,6 +169,63 @@ static int pylal_inline_string_set(PyObject *obj, PyObject *val, void *data)
 }
 
 
+static PyObject *end_get(PyObject *obj, void *null)
+{
+	return PyObject_CallFunction(LIGOTimeGPSType, "ii", ((gstlal_GSTLALSnglInspiral *) obj)->row.end.gpsSeconds, ((gstlal_GSTLALSnglInspiral *) obj)->row.end.gpsNanoSeconds);
+}
+
+
+static int end_set(PyObject *obj, PyObject *val, void *null)
+{
+	int end_time, end_time_ns;
+	PyObject *converted = PyObject_CallFunctionObjArgs(LIGOTimeGPSType, val, NULL);
+	PyObject *attr = NULL;;
+
+	if(!converted)
+		goto error;
+
+	attr = PyObject_GetAttrString(converted, "gpsSeconds");
+	if(!attr)
+		goto error;
+	end_time = PyInt_AsLong(attr);
+	Py_DECREF(attr);
+	attr = PyObject_GetAttrString(converted, "gpsNanoSeconds");
+	if(!attr)
+		goto error;
+	end_time_ns = PyInt_AsLong(attr);
+	Py_DECREF(attr);
+	Py_DECREF(converted);
+
+	XLALGPSSet(&((gstlal_GSTLALSnglInspiral *) obj)->row.end, end_time, end_time_ns);
+
+	return 0;
+
+error:
+	Py_XDECREF(converted);
+	Py_XDECREF(attr);
+	return -1;
+}
+
+
+static PyObject *template_id_get(PyObject *obj, void *null)
+{
+	return PyInt_FromLong(((gstlal_GSTLALSnglInspiral *) obj)->row.Gamma[0]);
+}
+
+
+static int template_id_set(PyObject *obj, PyObject *val, void *null)
+{
+	int template_id = PyInt_AsLong(val);
+
+	if(template_id == -1 && PyErr_Occurred())
+		return -1;
+
+	((gstlal_GSTLALSnglInspiral *) obj)->row.Gamma[0] = template_id;
+
+	return 0;
+}
+
+
 static PyObject *snr_component_get(PyObject *obj, void *data)
 {
 	COMPLEX8TimeSeries *snr = ((gstlal_GSTLALSnglInspiral *) obj)->snr;
@@ -209,6 +270,8 @@ static struct PyGetSetDef getset[] = {
 	{"ifo", pylal_inline_string_get, pylal_inline_string_set, "ifo", &(struct pylal_inline_string_description) {offsetof(gstlal_GSTLALSnglInspiral, row.ifo), LIGOMETA_IFO_MAX}},
 	{"search", pylal_inline_string_get, pylal_inline_string_set, "search", &(struct pylal_inline_string_description) {offsetof(gstlal_GSTLALSnglInspiral, row.search), LIGOMETA_SEARCH_MAX}},
 	{"channel", pylal_inline_string_get, pylal_inline_string_set, "channel", &(struct pylal_inline_string_description) {offsetof(gstlal_GSTLALSnglInspiral, row.channel), LIGOMETA_CHANNEL_MAX}},
+	{"end", end_get, end_set, "end", NULL},
+	{"template_id", template_id_get, template_id_set, "template_id", NULL},
 	{"_snr_name", snr_component_get, NULL, ".snr.name", "_snr_name"},
 	{"_snr_epoch_gpsSeconds", snr_component_get, NULL, ".snr.epoch.gpsSeconds", "_snr_epoch_gpsSeconds"},
 	{"_snr_epoch_gpsNanoSeconds", snr_component_get, NULL, ".snr.epoch.gpsNanoSeconds", "_snr_epoch_gpsNanoSeconds"},
@@ -381,6 +444,21 @@ PyMODINIT_FUNC init_snglinspiraltable(void)
 
 	import_array();
 
+	/* LIGOTimeGPS */
+
+	{
+	PyObject *lal = PyImport_ImportModule("lal");
+	if(!lal)
+		return;
+	LIGOTimeGPSType = PyDict_GetItemString(PyModule_GetDict(lal), "LIGOTimeGPS");
+	if(!LIGOTimeGPSType) {
+		Py_DECREF(lal);
+		return;
+	}
+	Py_INCREF(LIGOTimeGPSType);
+	Py_DECREF(lal);
+	}
+
 	/* SnglInspiralTable */
 	if(PyType_Ready(&gstlal_GSTLALSnglInspiral_Type) < 0)
 		return;
diff --git a/gstlal-inspiral/python/snglinspiraltable.py b/gstlal-inspiral/python/snglinspiraltable.py
index a170331ba17102a052e480804d5229f3ceafbf5f..9b40ca3641f4a487392888820fb176e2f776aa2d 100644
--- a/gstlal-inspiral/python/snglinspiraltable.py
+++ b/gstlal-inspiral/python/snglinspiraltable.py
@@ -30,7 +30,6 @@ class GSTLALSnglInspiral(_snglinspiraltable.GSTLALSnglInspiral):
 	process_id_type = ilwd.get_ilwdchar_class("process", "process_id")
 	event_id_type = ilwd.get_ilwdchar_class("sngl_inspiral", "event_id")
 
-	end = lsctables.gpsproperty("end_time", "end_time_ns")
 	spin1 = lsctables.SnglInspiral.spin1
 	spin2 = lsctables.SnglInspiral.spin2
 
@@ -83,16 +82,3 @@ class GSTLALSnglInspiral(_snglinspiraltable.GSTLALSnglInspiral):
 	@snr_time_series.deleter
 	def snr_time_series(self):
 		self._snr_time_series_deleter()
-
-	#
-	# simulate template_id column
-	# FIXME:  add a proper column for this
-	#
-
-	@property
-	def template_id(self):
-		return int(self.Gamma0)
-
-	@template_id.setter
-	def template_id(self, template_id):
-		self.Gamma0 = float(template_id)