#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include "cmunipack.h"
#include "framesetclass.h"
#include "phtfileclass.h"

PyObject *cmpack_error(int code);
PyObject *err_closed(void);
PyObject *return_datetime(CmpackDateTime *dt);

static void update_params(FrameSet* self)
{
	cmpack_fset_get_info(self->f, CMPACK_FS_FRAME_SIZE |
		CMPACK_FS_OBJECT | CMPACK_FS_LOCATION, &self->p);
	self->p_valid = 1;
}

static PyObject *
FrameSet_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    FrameSet *self = (FrameSet*)type->tp_alloc(type, 0);
    if (self != NULL) 
		self->f = NULL;
    return (PyObject *)self;
}

static void
FrameSet_dealloc(FrameSet* self)
{
	if (self->f) {
		cmpack_fset_destroy(self->f);
		self->f = NULL;
	}
    self->ob_base.ob_type->tp_free((PyObject*)self);
}

static int
FrameSet_init(FrameSet *self, PyObject *args)
{
	int i;
	PyObject *objlist, *aplist;
	CmpackCatObject obj;
	CmpackPhtAperture aper;

    if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &objlist, &PyList_Type, &aplist))
        return -1;

	if (self->f) {
		cmpack_fset_destroy(self->f);
		self->f = NULL;
	}
	self->f = cmpack_fset_init();
	Py_ssize_t count = PyList_Size(objlist);
	for (i=0; i<count; i++) {
		obj.id = PyLong_AsLong(PyList_GetItem(objlist, i));
		cmpack_fset_add_object(self->f, CMPACK_OM_ID, &obj);
	}
	count = PyList_Size(aplist);
	for (i=0; i<count; i++) {
		aper.id = PyLong_AsLong(PyList_GetItem(aplist, i));
		cmpack_fset_add_aperture(self->f, CMPACK_PA_ID, &aper);
	}
	self->p_valid = 0;
    return 0;
}

static PyObject *
FrameSet_test(FrameSet *self, PyObject *args)
{
	char *filename;
	PyObject *res;

	if (!PyArg_ParseTuple(args, "es", Py_FileSystemDefaultEncoding, &filename))
		return NULL;

	res = PyBool_FromLong(cmpack_fset_test(filename)!=0);
	PyMem_Free(filename);
	return res;
}

static PyObject *
FrameSet_copy(FrameSet *self, PyObject *args)
{
	int res;
    CmpackFrameSet *newf; 

	if (!self->f)
		return err_closed();

	newf = cmpack_fset_init();
	if (!newf) {
		PyErr_SetString(PyExc_MemoryError, "Memory allocation error.");
		return NULL;
	}
	res = cmpack_fset_copy(newf, self->f);
	if (res!=0) {
		cmpack_fset_destroy(newf);
		return cmpack_error(res);
	}
	return FrameSet_FromHandle(newf);
}

static PyObject *
FrameSet_object_name(FrameSet *self, void *data)
{
	if (!self->f)
		return err_closed();
	if (!self->p_valid)
		update_params(self);

	if (self->p.objcoords.designation) 
		return PyUnicode_FromString(self->p.objcoords.designation);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_right_ascension(FrameSet *self, void *data)
{
	if (!self->f)
		return err_closed();
	if (!self->p_valid)
		update_params(self);

	if (self->p.objcoords.ra_valid)
		return PyFloat_FromDouble(self->p.objcoords.ra);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_declination(FrameSet *self, void *data)
{
	if (!self->f)
		return err_closed();
	if (!self->p_valid)
		update_params(self);

	if (self->p.objcoords.dec_valid)
		return PyFloat_FromDouble(self->p.objcoords.dec);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_object(FrameSet *self, void *data)
{
	PyObject *res = PyTuple_New(3);
	PyTuple_SET_ITEM(res, 0, FrameSet_object_name(self, data));
	PyTuple_SET_ITEM(res, 1, FrameSet_right_ascension(self, data));
	PyTuple_SET_ITEM(res, 2, FrameSet_declination(self, data));
	return res;
}

static PyObject *
FrameSet_location_name(FrameSet *self, void *data)
{
	if (!self->f)
		return err_closed();
	if (!self->p_valid)
		update_params(self);

	if (self->p.location.designation) 
		return PyUnicode_FromString(self->p.location.designation);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_longitude(FrameSet *self, void *data)
{
	if (!self->f)
		return err_closed();
	if (!self->p_valid)
		update_params(self);

	if (self->p.location.lon_valid)
		return PyFloat_FromDouble(self->p.location.lon);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_latitude(FrameSet *self, void *data)
{
	if (!self->f)
		return err_closed();
	if (!self->p_valid)
		update_params(self);

	if (self->p.location.lat_valid)
		return PyFloat_FromDouble(self->p.location.lat);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_location(FrameSet *self, void *data)
{
	PyObject *res = PyTuple_New(3);
	PyTuple_SET_ITEM(res, 0, FrameSet_location_name(self, data));
	PyTuple_SET_ITEM(res, 1, FrameSet_longitude(self, data));
	PyTuple_SET_ITEM(res, 2, FrameSet_latitude(self, data));
	return res;
}

static PyObject *
FrameSet_frames(FrameSet *self, void *data)
{
	int i, count;
	PyObject *res;
	CmpackFrameInfo fi;

	if (!self->f)
		return err_closed();

	count = cmpack_fset_frame_count(self->f);
	res = PyList_New(count);
	cmpack_fset_rewind(self->f);
	i = 0;
	while (!cmpack_fset_eof(self->f)) {
		cmpack_fset_get_frame(self->f, CMPACK_FI_ID, &fi);
		PyList_SET_ITEM(res, i++, PyLong_FromLong(fi.frame_id));
		cmpack_fset_next(self->f);
	}
	return res;
}

static PyObject *
FrameSet_stars(FrameSet *self, void *data)
{
	int i, count;
	PyObject *res;
	CmpackCatObject obj;

	if (!self->f)
		return err_closed();

	count = cmpack_fset_object_count(self->f);
	res = PyList_New(count);
	for (i=0; i<count; i++) {
		cmpack_fset_get_object(self->f, i, CMPACK_OM_ID, &obj);
		PyList_SET_ITEM(res, i, PyLong_FromLong(obj.id));
	}
	return res;
}

static PyObject *
FrameSet_apertures(FrameSet *self, void *data)
{
	int i, count;
	PyObject *res;
	CmpackPhtAperture aper;

	if (!self->f)
		return err_closed();

	count = cmpack_fset_aperture_count(self->f);
	res = PyList_New(count);
	for (i=0; i<count; i++) {
		cmpack_fset_get_aperture(self->f, i, CMPACK_PA_ID, &aper);
		PyList_SET_ITEM(res, i, PyLong_FromLong(aper.id));
	}
	return res;
}

static PyObject *
FrameSet_frame_id(FrameSet *self, void *data)
{
	CmpackFrameInfo fi;

	if (!self->f)
		return err_closed();

	if (cmpack_fset_get_frame(self->f, CMPACK_FI_ID, &fi)==0)
		return PyLong_FromLong(fi.frame_id);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_date_time(FrameSet *self, void *data)
{
	CmpackFrameInfo fi;
	CmpackDateTime dt;

	if (!self->f)
		return err_closed();

	if (cmpack_fset_get_frame(self->f, CMPACK_FI_JULDAT, &fi)==0) {
		if (cmpack_decodejd(fi.juldat, &dt)==0)
			return return_datetime(&dt);
	}
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_julian_date(FrameSet *self, void *data)
{
	CmpackFrameInfo fi;

	if (!self->f)
		return err_closed();

	if (cmpack_fset_get_frame(self->f, CMPACK_FI_JULDAT, &fi)==0) 
		return PyFloat_FromDouble(fi.juldat);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_filter(FrameSet *self, void *data)
{
	CmpackFrameInfo fi;

	if (!self->f)
		return err_closed();

	if (cmpack_fset_get_frame(self->f, CMPACK_FI_FILTER, &fi)==0) {
		if (fi.filter)
			return PyUnicode_FromString(fi.filter);
	}
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_offset(FrameSet *self, void *data)
{
	CmpackFrameInfo fi;

	if (!self->f)
		return err_closed();

	if (cmpack_fset_get_frame(self->f, CMPACK_FI_OFFSET, &fi)==0)
		return Py_BuildValue("dd", fi.offset[0], fi.offset[1]);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_rewind(FrameSet *self, PyObject *args)
{
	if (!self->f)
		return err_closed();

	if (cmpack_fset_rewind(self->f)==0)
		Py_RETURN_TRUE;
	Py_RETURN_FALSE;
}

static PyObject *
FrameSet_next(FrameSet *self, PyObject *args)
{
	if (!self->f)
		return err_closed();

	if (cmpack_fset_next(self->f)==0)
		Py_RETURN_TRUE;
	Py_RETURN_FALSE;
}

static PyObject *
FrameSet_go_to(FrameSet *self, PyObject *args)
{
	int id;

	if (!PyArg_ParseTuple(args, "i", &id))
		return NULL;

	if (!self->f)
		return err_closed();

	if (cmpack_fset_find_frame(self->f, id)==0)
		Py_RETURN_TRUE;
	Py_RETURN_FALSE;
}

static PyObject *
FrameSet_append(FrameSet *self, PyObject *args)
{
	int id;
	PhtFile *frame;

	if (!PyArg_ParseTuple(args, "iO!", &id, &PhtFileType, &frame))
		return NULL;

	if (!self->f || !frame->f)
		return err_closed();

	if (cmpack_fset_append_frame(self->f, frame->f, id, NULL)==0)
		Py_RETURN_TRUE;
	Py_RETURN_FALSE;
}

static PyObject *
FrameSet_delete(FrameSet *self, PyObject *args)
{
	if (!self->f)
		return err_closed();

	cmpack_fset_delete_frame(self->f);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_clear(FrameSet *self, PyObject *args)
{
	if (!self->f)
		return err_closed();

	cmpack_fset_rewind(self->f);
	while (!cmpack_fset_eof(self->f))
		cmpack_fset_delete_frame(self->f);
	Py_RETURN_NONE;
}

static PyObject *
FrameSet_get_mag(FrameSet *self, PyObject *args)
{
	int i, j, object, aperture;
	CmpackPhtData data;

	if (!PyArg_ParseTuple(args, "ii", &object, &aperture))
		return NULL;

	if (!self->f)
		return err_closed();

	i = cmpack_fset_find_object(self->f, object);
	if (i<0)
		Py_RETURN_NONE;
	j = cmpack_fset_find_aperture(self->f, aperture);
	if (j<0)
		Py_RETURN_NONE;

	cmpack_fset_get_data(self->f, i, j, &data);
	if (!data.mag_valid)
		return Py_BuildValue("OO", Py_None, Py_None);
	else
		return Py_BuildValue("dd", data.magnitude, data.mag_error);
}

static PyObject *
FrameSet_get_all(FrameSet *self, PyObject *args)
{
	int i, j, aperture, count;
	PyObject *res, *val;
	CmpackCatObject obj;
	CmpackPhtData data;

	if (!PyArg_ParseTuple(args, "i", &aperture))
		return NULL;

	if (!self->f)
		return err_closed();

	j = cmpack_fset_find_aperture(self->f, aperture);
	if (j<0)
		Py_RETURN_NONE;

	res = PyDict_New();
	if (res) {
		count = cmpack_fset_object_count(self->f);
		for (i=0; i<count; i++) {
			if (cmpack_fset_get_object(self->f, i, CMPACK_OM_ID, &obj)==0) {
				cmpack_fset_get_data(self->f, i, j, &data);
				if (!data.mag_valid)
					val = Py_BuildValue("OO", Py_None, Py_None);
				else
					val = Py_BuildValue("dd", data.magnitude, data.mag_error);
				PyDict_SetItem(res,PyLong_FromLong(obj.id), val);
			}
		}
	}
	return res;
}

static PyObject *
FrameSet_import(PyObject *self, PyObject *args)
{
	int res;
	CmpackFrameSet *f;
    char *filename; 

    if (!PyArg_ParseTuple(args, "es", Py_FileSystemDefaultEncoding, &filename))
        return NULL;

	res = cmpack_fset_load(&f, filename, 0);
	PyMem_Free(filename);
	if (res!=0)
		return cmpack_error(res);

	return FrameSet_FromHandle(f);
}

static PyObject *
FrameSet_export(FrameSet *self, PyObject *args)
{
	int j, res, aperture;
    char *filename;

    if (!PyArg_ParseTuple(args, "esi", Py_FileSystemDefaultEncoding, &filename, &aperture))
        return NULL;

	if (!self->f) 
		return err_closed();

	j = cmpack_fset_find_aperture(self->f, aperture);
	if (j<0)
		Py_RETURN_NONE;

	res = cmpack_fset_export(self->f, filename, j);
	PyMem_Free(filename);
	if (res!=0)
		return cmpack_error(res);

	Py_RETURN_TRUE;
}

static PyObject *
FrameSet_light_curve(FrameSet *self, PyObject *args)
{
	int res, variable, comparison, aperture;
	int jd_col, mag_col;
	double jd, mag, err;
    PyObject *retval;
	CmpackLCurve *lc;
	CmpackTable *table;

    if (!PyArg_ParseTuple(args, "iii", &variable, &comparison, &aperture))
        return NULL;

	if (!self->f)
		return err_closed();

	lc = cmpack_lcurve_init();
	cmpack_lcurve_set_var(lc, &variable, 1);
	cmpack_lcurve_set_comp(lc, &comparison, 1);
	cmpack_lcurve_set_aperture(lc, aperture);
	res = cmpack_lcurve(lc, self->f, &table, CMPACK_LCURVE_DEFAULT);
	cmpack_lcurve_destroy(lc);
	if (res!=0) 
		return cmpack_error(res);

	jd_col = cmpack_tab_find_column(table, "JD");
	mag_col = cmpack_tab_find_column(table, "V-C");
	
	retval = PyList_New(0);
	res = cmpack_tab_rewind(table);
	while (res==0) {
		if (cmpack_tab_gtdd(table, jd_col, &jd)==0 && cmpack_tab_gtdd(table, mag_col, &mag)==0 &&
			cmpack_tab_gtdd(table, mag_col+1, &err)==0) {
				PyList_Append(retval, Py_BuildValue("ddd", jd, mag, err));
		}
		res = cmpack_tab_next(table);
	}
	cmpack_tab_destroy(table);
	return retval;
}

static PyObject *
FrameSet_light_curve2(FrameSet *self, PyObject *args)
{
	int res, frame, variable, comparison, aperture;
	int frame_col, jd_col, mag_col;
	double jd, mag, err;
    PyObject *retval;
	CmpackLCurve *lc;
	CmpackTable *table;

    if (!PyArg_ParseTuple(args, "iii", &variable, &comparison, &aperture))
        return NULL;

	if (!self->f)
		return err_closed();

	lc = cmpack_lcurve_init();
	cmpack_lcurve_set_var(lc, &variable, 1);
	cmpack_lcurve_set_comp(lc, &comparison, 1);
	cmpack_lcurve_set_aperture(lc, aperture);
	res = cmpack_lcurve(lc, self->f, &table, CMPACK_LCURVE_FRAME_IDS);
	cmpack_lcurve_destroy(lc);
	if (res!=0) 
		return cmpack_error(res);

	frame_col = cmpack_tab_find_column(table, "FRAME");
	jd_col = cmpack_tab_find_column(table, "JD");
	mag_col = cmpack_tab_find_column(table, "V-C");

	retval = PyDict_New();
	res = cmpack_tab_rewind(table);
	while (res==0) {
		if (cmpack_tab_gtdi(table, frame_col, &frame)==0 && cmpack_tab_gtdd(table, jd_col, &jd)==0 && 
			cmpack_tab_gtdd(table, mag_col, &mag)==0 && cmpack_tab_gtdd(table, mag_col+1, &err)==0) {
				PyDict_SetItem(retval, PyLong_FromLong(frame), Py_BuildValue("ddd", jd, mag, err));
		}
		res = cmpack_tab_next(table);
	}
	cmpack_tab_destroy(table);
	return retval;
}

static PyObject *
FrameSet_track_list(FrameSet *self, PyObject *args)
{
	int res;
	CmpackFrameInfo fi;
    PyObject *retval;

	if (!self->f)
		return err_closed();

	retval = PyList_New(0);
	res = cmpack_fset_rewind(self->f);
	while (res==0) {
		if (cmpack_fset_get_frame(self->f, CMPACK_FI_JULDAT | CMPACK_FI_OFFSET, &fi)==0) 
			PyList_Append(retval, Py_BuildValue("ddd", fi.juldat, fi.offset[0], fi.offset[1]));
		res = cmpack_fset_next(self->f);
	}
	return retval;
}

static PyObject *
FrameSet_track_list2(FrameSet *self, PyObject *args)
{
	int res;
	CmpackFrameInfo fi;
    PyObject *retval;

	if (!self->f)
		return err_closed();

	retval = PyDict_New();
	res = cmpack_fset_rewind(self->f);
	while (res==0) {
		if (cmpack_fset_get_frame(self->f, CMPACK_FI_ID | CMPACK_FI_JULDAT | CMPACK_FI_OFFSET, &fi)==0) 
			PyDict_SetItem(retval, PyLong_FromLong(fi.frame_id), Py_BuildValue("ddd", fi.juldat, fi.offset[0], fi.offset[1]));
		res = cmpack_fset_next(self->f);
	}
	return retval;
}

static PyObject *
FrameSet_magdev_curve(FrameSet *self, PyObject *args)
{
	int id, res, comparison = CMPACK_MFIND_AUTO, aperture;
	int id_col, mag_col, dev_col;
	double mag, dev, threshold = 60;
    PyObject *retval;
	CmpackMuniFind *lc;
	CmpackTable *table;

    if (!PyArg_ParseTuple(args, "i|di", &aperture, &threshold, &comparison))
        return NULL;

	if (!self->f)
		return err_closed();

	lc = cmpack_mfind_init();
	cmpack_mfind_set_threshold(lc, threshold);
	cmpack_mfind_set_comparison(lc, comparison);
	cmpack_mfind_set_aperture(lc, aperture);
	res = cmpack_mfind(lc, self->f, &table, CMPACK_MFIND_DEFAULT);
	comparison = cmpack_mfind_get_comparison(lc);
	cmpack_mfind_destroy(lc);
	if (res!=0) 
		return cmpack_error(res);

	id_col = cmpack_tab_find_column(table, "INDEX");
	mag_col = cmpack_tab_find_column(table, "MEAN_MAG");
	dev_col = cmpack_tab_find_column(table, "STDEV");
	
	retval = PyList_New(0);
	res = cmpack_tab_rewind(table);
	while (res==0) {
		if (cmpack_tab_gtdi(table, id_col, &id)==0 && cmpack_tab_gtdd(table, mag_col, &mag)==0 &&
			cmpack_tab_gtdd(table, dev_col, &dev)==0) {
				PyList_Append(retval, Py_BuildValue("idd", id, mag, dev));
		}
		res = cmpack_tab_next(table);
	}
	cmpack_tab_destroy(table);
	return Py_BuildValue("iN", comparison, retval);
}

static PyObject *
FrameSet_magdev_curve2(FrameSet *self, PyObject *args)
{
	int id, res, comparison = CMPACK_MFIND_AUTO, aperture;
	int id_col, mag_col, dev_col;
	double mag, dev, threshold = 60;
    PyObject *retval;
	CmpackMuniFind *lc;
	CmpackTable *table;

    if (!PyArg_ParseTuple(args, "i|di", &aperture, &threshold, &comparison))
        return NULL;

	if (!self->f)
		return err_closed();

	lc = cmpack_mfind_init();
	cmpack_mfind_set_threshold(lc, threshold);
	cmpack_mfind_set_comparison(lc, comparison);
	cmpack_mfind_set_aperture(lc, aperture);
	res = cmpack_mfind(lc, self->f, &table, CMPACK_MFIND_DEFAULT);
	comparison = cmpack_mfind_get_comparison(lc);
	cmpack_mfind_destroy(lc);
	if (res!=0) 
		return cmpack_error(res);

	id_col = cmpack_tab_find_column(table, "INDEX");
	mag_col = cmpack_tab_find_column(table, "MEAN_MAG");
	dev_col = cmpack_tab_find_column(table, "STDEV");
	
	retval = PyDict_New();
	res = cmpack_tab_rewind(table);
	while (res==0) {
		if (cmpack_tab_gtdi(table, id_col, &id)==0 && cmpack_tab_gtdd(table, mag_col, &mag)==0 &&
			cmpack_tab_gtdd(table, dev_col, &dev)==0) {
				PyDict_SetItem(retval, PyLong_FromLong(id), Py_BuildValue("dd", mag, dev));
		}
		res = cmpack_tab_next(table);
	}
	cmpack_tab_destroy(table);
	return Py_BuildValue("iN", comparison, retval);
}

static PyGetSetDef FrameSet_getset[] = {
	{"object", (getter)FrameSet_object, NULL, 
	"Object designation and coordinates"},
	{"location", (getter)FrameSet_location, NULL,
	"Observatory designation and coordinates"},
	{"frames", (getter)FrameSet_frames, NULL,
	"List of frame identifiers"},
	{"apertures", (getter)FrameSet_apertures, NULL,
	"List of aperture identifiers"},
	{"stars", (getter)FrameSet_stars, NULL,
	"List of star identifiers"},

	{"frame_id", (getter)FrameSet_frame_id, NULL,
	"Frame identifier"},
	{"date_time", (getter)FrameSet_date_time, NULL,
	"Date and time of observation"},
	{"julian_date", (getter)FrameSet_julian_date, NULL,
	"Julian date of observation"},
	{"filter", (getter)FrameSet_filter, NULL,
	"Color filter designation"},
	{"offset", (getter)FrameSet_offset, NULL,
	"Frame offset in x and y coordinates with respect to the reference frame"},
	{NULL}
};

static PyMethodDef FrameSet_methods[] = {
	{"test", (PyCFunction)FrameSet_test, METH_VARARGS | METH_STATIC,
	"Check if the file is a read-all file"},
	{"import", (PyCFunction)FrameSet_import, METH_VARARGS | METH_STATIC,
	"Load frame set from a file"},

	{"copy", (PyCFunction)FrameSet_copy, METH_NOARGS,
	"Make copy of the frame set"},
	{"export", (PyCFunction)FrameSet_export, METH_KEYWORDS,
	"Save table to a file"},
	{"rewind", (PyCFunction)FrameSet_rewind, METH_NOARGS,
	"Activate the first frame in the set"},
	{"next", (PyCFunction)FrameSet_next, METH_NOARGS,
	"Activate the frame after the active"},
	{"go_to", (PyCFunction)FrameSet_go_to, METH_VARARGS,
	"Activate a frame specified by its identifier"},
	{"append", (PyCFunction)FrameSet_append, METH_VARARGS,
	"Append a new frame"},
	{"delete", (PyCFunction)FrameSet_delete, METH_NOARGS,
	"Delete the active frame"},
	{"clear", (PyCFunction)FrameSet_clear, METH_NOARGS,
	"Clear all frames"},
	{"light_curve", (PyCFunction)FrameSet_light_curve, METH_VARARGS,
	"Makes a light curve"},
	{"light_curve2", (PyCFunction)FrameSet_light_curve2, METH_VARARGS,
	"Makes a light curve with frame identifiers"},
	{"track_list", (PyCFunction)FrameSet_track_list, METH_NOARGS,
	"Makes a track-list curve"},
	{"track_list2", (PyCFunction)FrameSet_track_list2, METH_NOARGS,
	"Makes a track-list curve with frame identifiers"},
	{"magdev_curve", (PyCFunction)FrameSet_magdev_curve, METH_VARARGS,
	"Makes a mag-dev curve (for finding variables)"},
	{"magdev_curve2", (PyCFunction)FrameSet_magdev_curve2, METH_VARARGS,
	"Makes a mag-dev curve (for finding variables)"},

	{"get_mag", (PyCFunction)FrameSet_get_mag, METH_VARARGS,
	"Get magnitude for given star and aperture"},
	{"get_all", (PyCFunction)FrameSet_get_all, METH_VARARGS,
	"Get magnitude for all stars as a dictionary"},
    {NULL}  /* Sentinel */
};

PyTypeObject FrameSetType = {
    PyObject_HEAD_INIT(NULL)
    .tp_name = "cmpack.FrameSet",          /*tp_name*/
    .tp_basicsize = sizeof(FrameSet),           /*tp_basicsize*/
    .tp_dealloc = (destructor)FrameSet_dealloc,           /*tp_dealloc*/
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /*tp_flags*/
    .tp_doc = "Frame set",        /* tp_doc */
    .tp_methods = FrameSet_methods,           /* tp_methods */
    .tp_getset = FrameSet_getset,            /* tp_getset */
    .tp_init = (initproc)FrameSet_init,      /* tp_init */
    .tp_new = FrameSet_new                 /* tp_new */
};

PyObject *
FrameSet_FromHandle(CmpackFrameSet *f)
{
	FrameSet *pDoc = PyObject_New(FrameSet, &FrameSetType);
	if (pDoc) {
		pDoc->f = f;
		pDoc->p_valid = 0;
	}
	return (PyObject*)pDoc;
}


PyTypeObject *FrameSet_Type(void)
{
	return &FrameSetType;
}
