/**
 * \brief Display Calibration data.
 */
std::ostream&	operator<<(std::ostream& out,
			const Astro::Calibration& calibration) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "display calibration object");
	out << "calibration:     ";
	out << calibration.id << std::endl;
	out << "when:            ";
	out << calibration.timeago << std::endl;
	out << "coefficients:    ";
	out << stringprintf("[ %10.6f, %10.6f, %10.6f;",
		calibration.coefficients[0],
		calibration.coefficients[1],
		calibration.coefficients[2]);
	out << std::endl;
	out << "           :     ";
	out << stringprintf("  %10.6f, %10.6f, %10.6f   ]",
		calibration.coefficients[3],
		calibration.coefficients[4],
		calibration.coefficients[5]);
	out << std::endl;
	out << "points:          ";
	out << calibration.points.length() << std::endl;
	for (unsigned int i = 0; i < calibration.points.length(); i++) {
		out << "                 ";
		out << calibration.points[i] << std::endl;
	}
	return out;
}
/**
 * \brief Construct a camera from a camera description
 *
 * \param name		Name of the camera
 * \return 		Camera with that name
 */
CameraPtr	QhyCameraLocator::getCamera0(const DeviceName& name) {
	QhyName	qhyname(name);
	if (!qhyname.isCamera(name)) {
		std::string	msg = stringprintf("%s is not a Camera name",
			name.toString().c_str());
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}

	// scan the devices and get 
	std::vector<usb::DevicePtr>	d = context.devices();
	std::vector<usb::DevicePtr>::const_iterator	i;
	for (i = d.begin(); i != d.end(); i++) {
		usb::DevicePtr	dptr = *i;
		int	busnumber = dptr->getBusNumber();
		int	deviceaddress = dptr->getDeviceAddress();
		if ((busnumber == qhyname.busnumber()) &&
			(deviceaddress == qhyname.deviceaddress())) {
			dptr->open();
			return CameraPtr(new QhyCamera(dptr));
		}
	}

	// failure to construct the camera
	std::string	msg = stringprintf("cannot create camera from '%s'",
		name.toString().c_str());
	throw std::runtime_error(msg);
}
void	InstrumentTest::testInstrumentComponentTable() {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "testInstrumentComponentTable() begin");
	Database	database = DatabaseFactory::get(dbfilename);

	discover::InstrumentComponentTable	table(database);
	std::string	query("delete from instrumentcomponents;");
	database->query(query);
	std::string	names[2] = { "INSTRUMENT", "TELESCOPE" };

	for (int j = 0; j < 2; j++) {
		for (int i = 0; i < 5; i++) {
			discover::InstrumentComponentKey	key(names[j],
				discover::InstrumentComponentKey::CCD, i);
			discover::InstrumentComponent	component(key, "blubber",
				stringprintf("ccd:sx/1-2-3/%d", i));
			discover::InstrumentComponentRecord	record(component);

			table.add(record);
		}
		for (int i = 0; i < 5; i++) {
			discover::InstrumentComponentKey	key(names[j],
				discover::InstrumentComponentKey::Cooler, i);
			discover::InstrumentComponent	component(key, "blubber",
				stringprintf("cooler:sx/1-2-3/%d", i));
			discover::InstrumentComponentRecord	record(component);

			table.add(record);
		}
	}

	debug(LOG_DEBUG, DEBUG_LOG, 0, "testInstrumentComponentTable() end");
}
Example #4
0
/// move die over board
void Game::makeMove(Move move, bool storeMove) {
  //TODO: check correctness! (Game::makeMove)
  KBX::Logger log("DieState");
  //// perform move
  DieState& dieState = this->_dice[move.dieIndex];
  log.info(stringprintf("initial state: %d", dieState.getCurrentState()));
  // delete die from current position on board
  this->_fields[dieState.x()][dieState.y()] = CLEAR;
  // get directions for horizontal movement (aka x coordinate)
  int directionX, directionY;
  if (move.rel.dx < 0) {
    directionX = WEST;
  } else {
    directionX = EAST;
  }
  // get directions for vertical movement (aka y coordinate)
  if (move.rel.dy < 0) {
    directionY = SOUTH;
  } else {
    directionY = NORTH;
  }
  // assume move to go first in y direction
  int stepsFirst = abs(move.rel.dy);
  int directionFirst = directionY;
  int stepsSec = abs(move.rel.dx);
  int directionSec = directionX;
  // swap values if move goes in x direction first
  if (move.rel.firstX) {
    swap(stepsFirst, stepsSec);
    swap(directionFirst, directionSec);
  }
  // traverse through dice states
  for (size_t i = stepsFirst; i > 0; i--) {
    // rotate in first direction
    dieState.moveOneStep(directionFirst);
    log.info(stringprintf("new state: %d", dieState.getCurrentState()));
  }
  for (size_t i = stepsSec; i > 0; i--) {
    // rotate in second direction
    dieState.moveOneStep(directionSec);
    log.info(stringprintf("new state: %d", dieState.getCurrentState()));
  }
  // delete old die on this position before moving new die to it
  int keyOldDie = this->_fields[dieState.x()][dieState.y()];
  if (keyOldDie != CLEAR) {
    this->_dice[keyOldDie].kill();
  }
  // if the move should be stored, do so
  if(storeMove){
    this->_moveStackPending.clear();
    this->_deathStackPending.clear();
    this->_moveStack.push_front(move);
    this->_deathStack.push_front(keyOldDie);
  }
  // move die to new position
  this->_fields[dieState.x()][dieState.y()] = move.dieIndex;
  this->_nextPlayer = inverse(this->_nextPlayer);
}
void	CelestronMount::Goto(const RaDec& radec) {
	std::string	cmd;
	if (version > 106) {
		cmd = stringprintf("r%08X,%08X",
			angle32(radec.ra()), angle32(radec.dec()));
	} else {
		cmd = stringprintf("R%04X,%04X",
			angle16(radec.ra()), angle16(radec.dec()));
	}
	debug(LOG_DEBUG, DEBUG_LOG, 0, "command sent: %s", cmd.c_str());
	write(cmd);
	getprompt();
}
void	CelestronMount::Goto(const AzmAlt& azmalt) {
	std::string	cmd;
	if (version > 202) {
		cmd = stringprintf("b%08X,%08X",
			angle32(azmalt.azm()), angle32(azmalt.alt()));
	} else {
		cmd = stringprintf("B%04X,%04X",
			angle16(azmalt.azm()), angle16(azmalt.alt()));
	}
	debug(LOG_DEBUG, DEBUG_LOG, 0, "command sent: %s", cmd.c_str());
	write(cmd);
	getprompt();
}
//////////////////////////////////////////////////////////////////////
// ProjectTable implementation
//////////////////////////////////////////////////////////////////////
ProjectRecord	ProjectTable::get(const std::string& name) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "retrieve project '%s'", name.c_str());
	std::string	condition = stringprintf("name = '%s'",
		database()->escape(name).c_str());
	std::list<ProjectRecord>	l = select(condition);
	if (0 == l.size()) {
		std::string	msg = stringprintf("no project '%s'",
			name.c_str());
		debug(LOG_DEBUG, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}
	return *(l.begin());
}
/**
 * \brief Get the filter name
 */
std::string	FilterWheel::filterName(size_t index) {
	if (index >= nFilters()) {
		std::string	msg = stringprintf("%u is too large", index);
		throw std::runtime_error(msg);
	}
	// get the properties
	Properties	properties(name().toString());
	try {
		return properties.getProperty(stringprintf("filter%u", index));
	} catch (...) {
		return stringprintf("%u", index);
	}
}
/**
 * \brief Retrieve a list of image types 
 *
 * \param index		index of the camera 
 */
std::vector<std::string>	AsiCameraLocator::imgtypes(int index) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "retrieving image types for %d", index);
	// make sure the index is valid
	if (index >= ASIGetNumOfConnectedCameras()) {
		std::string	msg = stringprintf("");
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}
	std::vector<std::string>	result;
	int	rc;
	if (!isopen(index)) {
		int	rc = ASIOpenCamera(index);
		debug(LOG_DEBUG, DEBUG_LOG, 0, "open camera %d: %d", index, rc);
		if (ASI_SUCCESS != rc) {
			std::string	msg = stringprintf("%d cannot open: %s",
				index, AsiCamera::error(rc).c_str());
			debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
			throw std::runtime_error(msg);
		}
	}
	ASI_CAMERA_INFO	camerainfo;
	if (ASI_SUCCESS != (rc = ASIGetCameraProperty(&camerainfo, index))) {
		std::string	msg = stringprintf("%d cannot get props: %s",
			index, AsiCamera::error(rc).c_str());
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}
	debug(LOG_DEBUG, DEBUG_LOG, 0, "got camera info for %d", index);
        int     imgtypeidx = 0;
        while (camerainfo.SupportedVideoFormat[imgtypeidx] != -1) {
                std::string     it = AsiCcd::imgtype2string(
                        camerainfo.SupportedVideoFormat[imgtypeidx]);
		result.push_back(it);
		imgtypeidx++;
	}
	if (!isopen(index)) {
		rc = ASICloseCamera(index);
		debug(LOG_DEBUG, DEBUG_LOG, 0, "close camera %d: %d",
			index, rc);
		if (ASI_SUCCESS != rc) {
			std::string	msg = stringprintf("%d cannot close: %s",
				index, AsiCamera::error(rc).c_str());
			debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
			throw std::runtime_error(msg);
		}
	}
	return result;
}
/**
 * \brief Construct a Mapped file
 */
MappedFile::MappedFile(const std::string& filename, size_t recordlength)
	: _filename(filename), _recordlength(recordlength) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "mapping file '%s'", filename.c_str());
	// stat the file
	struct stat	sb;
	if (stat(filename.c_str(), &sb) < 0) {
		std::string	msg = stringprintf("cannot stat '%s': %s",
			filename.c_str(), strerror(errno));
		debug(LOG_DEBUG, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}
	data_len = sb.st_size;
	if (0 != (data_len % _recordlength)) {
		debug(LOG_DEBUG, DEBUG_LOG, 0, "record length %u does not "
			"divide file size %u", recordlength, data_len);
		throw std::runtime_error("record length does not devide "
			"file size");
	}
	_nrecords = data_len / _recordlength;
	debug(LOG_DEBUG, DEBUG_LOG, 0, "file contains %u records", _nrecords);

	// open the file
	debug(LOG_DEBUG, DEBUG_LOG, 0, "open file '%s'", filename.c_str());
	int	fd = open(filename.c_str(), O_RDONLY);
	if (fd < 0) {
		std::string	msg = stringprintf("cannot open '%s': %s",
			filename.c_str(), strerror(errno));
		debug(LOG_DEBUG, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}

        // map the file into the address space
	debug(LOG_DEBUG, DEBUG_LOG, 0, "mapping '%s', length %u",
		filename.c_str(), data_len);
	data_ptr = (char *)mmap(NULL, sb.st_size, PROT_READ,
		MAP_FILE | MAP_PRIVATE, fd, 0);
	if ((void *)(-1) == data_ptr) {
		close(fd);
		std::string     msg = stringprintf("cannot map '%s': %s",
			filename.c_str(), strerror(errno));
		debug(LOG_DEBUG, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}

        // we can now close the file descriptor
        close(fd);
	debug(LOG_DEBUG, DEBUG_LOG, 0, "file '%s' mapped", filename.c_str());
}
void	writeimage(ImagePtr image) {
	std::string	filename = stringprintf("sim%03d.fits", counter);
	unlink(filename.c_str());
	FITSout	out(filename);
	out.write(image);
	counter++;
}
/**
 * \brief Set mosaic type from name
 *
 * This method ensures that only valid mosaic type names are used and
 * that the mosaic_type member variable is consistently set.
 * \param mosaic_name	string representation of color mosaic
 */
void	ImageBase::setMosaicType(const std::string& mosaic_name) {
	if (mosaic_name == "NONE") {
		setMosaicType(MosaicType::NONE);
		return;
	}
	if (mosaic_name == "RGGB") {
		setMosaicType(MosaicType::BAYER_RGGB);
		return;
	}
	if (mosaic_name == "GRBG") {
		setMosaicType(MosaicType::BAYER_GRBG);
		return;
	}
	if (mosaic_name == "GBRG") {
		setMosaicType(MosaicType::BAYER_GBRG);
		return;
	}
	if (mosaic_name == "BGGR") {
		setMosaicType(MosaicType::BAYER_BGGR);
		return;
	}
	std::string	msg = stringprintf("unknown mosaic name: %s",
		mosaic_name.c_str());
	debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
	throw std::runtime_error(msg);
}
/**
 * \brief Get a list of Starlight Express cameras.
 *
 * \param device	the type of devices we want to have listed
 * \return 		a vector of strings that uniquely descript devices
 */
std::vector<std::string>	QhyCameraLocator::getDevicelist(DeviceName::device_type device) {
	std::vector<std::string>	names;

	// list all devices from the context
	std::vector<usb::DevicePtr>	d = context.devices();
	std::vector<usb::DevicePtr>::const_iterator	i;
	for (i = d.begin(); i != d.end(); i++) {
		usb::DevicePtr	devptr = *i;
		// try to open all devices, and check whether they have
		// the right vendor id
		try {
			devptr->open();
			try {
				addname(names, devptr, device);
			} catch (std::runtime_error& x) {
				debug(LOG_DEBUG, DEBUG_LOG, 0, "found a non "
					"QHY device: %s", x.what());
			}
		} catch (std::exception& x) {
			std::string	msg = stringprintf("cannot work with "
				"device at bus=%d and addr=%d",
				devptr->getBusNumber(),
				devptr->getDeviceAddress());
			debug(LOG_ERR, DEBUG_LOG, 0, msg.c_str());
		}
	}

	// return the list of devices
	return names;
}
Analyzer::Analyzer(const ConstImageAdapter<double>& _baseimage,
	int _spacing, int _patchsize)
	: baseimage(_baseimage), spacing(_spacing), patchsize(_patchsize)  {
	if (_spacing < 0) {
		std::string	msg = stringprintf("invalid spacing %d",
			_spacing);
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::range_error(msg);
	}
	if (_patchsize < 0) {
		std::string	msg = stringprintf("invalid patchsize %d",
			_patchsize);
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::range_error(msg);
	}
}
/**
 * \brief Save an image in the directory, return the short name
 */
std::string	ImageDirectory::save(astro::image::ImagePtr image) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "saving an image");
	// create a temporary file name in the base directory
	char	buffer[1024];
	snprintf(buffer, sizeof(buffer), "%s/XXXXXXXX.fits", basedir().c_str());
	int	fd = mkstemps(buffer, 5);
	if (fd < 0) {
		std::string	cause = stringprintf("cannot create a tmp "
			"image file: %s", strerror(errno));
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", cause.c_str());
		throw std::runtime_error(cause);
	}
	unlink(buffer);
	close(fd);
	std::string	fullname(buffer);

	// construct the filename
	std::string	filename = basename(fullname);
	debug(LOG_DEBUG, DEBUG_LOG, 0, "image full name: %s, filename: %s",
		fullname.c_str(), filename.c_str());

	// write the file
	ImageDirectory::write(image, filename);

	// return the filename
	debug(LOG_DEBUG, DEBUG_LOG, 0, "image short name: %s",
		filename.c_str());
	return filename;
}
void	flat_correct(Image<ImagePixelType>& image,
		const Image<FlatPixelType>& flat) {
	ImagePixelType	max = std::numeric_limits<ImagePixelType>::max();

	// first check that image sizes match
	if (image.size() != flat.size()) {
		std::string	msg = stringprintf("size: image %s != flat %s",
			image.size().toString().c_str(),
			flat.size().toString().c_str());
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}

	// correct all pixels
	for (size_t offset = 0; offset < image.size().getPixels(); offset++) {
		ImagePixelType	ip = image.pixels[offset];
		// skip NaN pixels
		if (ip != ip) {
			continue;
		}
		FlatPixelType	dp = flat.pixels[offset];
		// turn off (make nan) pixels that are marked nan in the flat
		if (dp != dp) {
			ip = 0;
		} else {
			FlatPixelType	v = ip / dp;
			if (v > max) {
				ip = max;
			} else {
				ip = v;
			}
		}
		image.pixels[offset] = ip;
	}
}
/**
 * \brief Compute the product of two fourier transforms
 *
 * Upon reverse transform, this becomes the convolution product of the
 * original functions
 */
FourierImagePtr	operator*(const FourierImage& a, const FourierImage& b) {
	if (a.size() != b.size()) {
		std::string	msg = stringprintf(
			"image size mismatch: %s != %s",
			a.orig().toString().c_str(),
			b.orig().toString().c_str());
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}

	// construct the result image
	FourierImage	*result = new FourierImage(a.orig());

	// compute the product
	fftw_complex	*af = (fftw_complex *)a.pixels;
	fftw_complex	*bf = (fftw_complex *)b.pixels;
	fftw_complex	*cf = (fftw_complex *)result->pixels;
	size_t	nc = result->size().getPixels() / 2;
	for (unsigned int i = 0; i < nc; i++) {
		cf[i][0] = af[i][0] * bf[i][0] - af[i][1] * bf[i][1];
                cf[i][1] = af[i][1] * bf[i][0] + af[i][0] * bf[i][1];
	}

	// return the new image
	return FourierImagePtr(result);
}
static std::string	get_typename(const ProcessingStep *step) {
	try {
		return demangle(typeid(*step).name());
	} catch (std::bad_typeid& x) {
		return stringprintf("(unknown [%s])", x.what());
	}
}
/**
 * \brief default main function for focusing
 */
void	FocusWork::main(astro::thread::Thread<FocusWork>& thread) {
	if (!complete()) {
		debug(LOG_ERR, DEBUG_LOG, 0,
			"FocusWork is not completely configured");
		focusingstatus(Focusing::FAILED);
		return;
	}
	debug(LOG_DEBUG, DEBUG_LOG, 0, "starting focus process in [%d,%d]",
		min(), max());

	// prepare the set of focus items to base the focus computation on
	FocusItems	focusitems;

	// prepare 
	for (int step = 0; step < steps(); step++) {
		// find position
		unsigned short	position
			= min() + (step * (max() - min())) / (steps() - 1);
		debug(LOG_DEBUG, DEBUG_LOG, 0, "next position: %hu", position);

		// move to this position
		moveto(position);

		// get an image
		focusingstatus(Focusing::MEASURING);
		ccd()->startExposure(exposure());
		usleep(1000000 * exposure().exposuretime());
		ccd()->wait();
		ImagePtr	image = ccd()->getImage();
		debug(LOG_DEBUG, DEBUG_LOG, 0, "got an image of size %s",
			image->size().toString().c_str());

		// evaluate the image
		double	value = (*evaluator())(image);
		debug(LOG_DEBUG, DEBUG_LOG, 0, "evaluated to %f", value);

		// callback with the evaluated image
		callback(evaluator()->evaluated_image(), position, value);

		// add the information to a set
		focusitems.insert(FocusItem(position, value));
	}

	// now solve we need a suitable solver for the method
	int	targetposition = solver()->position(focusitems);
	if ((targetposition < min()) || (targetposition > max())) {
		std::string	msg = stringprintf(
			"could not find a focus position: %d", targetposition);
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		focusingstatus(Focusing::FAILED);
		return;
	}

	// move to the final focus position
	focusingstatus(Focusing::MOVING);
	moveto(targetposition);
	focusingstatus(Focusing::FOCUSED);
}
bool	ServiceSubset::has(service_type s) const {
	if (!validtype(s)) {
		std::string	msg = stringprintf("cannot check for invalid "
			"service code %d", (int)s);
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}
	return (_services & s) ? true : false;
}
void	ServiceSubset::unset(service_type s) {
	if (!validtype(s)) {
		std::string	msg = stringprintf("cannot unset invalid "
			"service code %d", (int)s);
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}
	_services &= ~s;
}
/**
 * \brief Name of the device
 *
 * For derived components, this only returns the device name of the
 * parent device, it is the client's responsibilty to retrieve the
 * correct subdevice of the parent device.
 */
DeviceName	InstrumentComponentDerived::devicename() {
	DeviceName	name = _instrument.devicename(_derivedfrom);
	if (type() != DeviceName::Ccd) {
		name.type(type());
		return name;
	} else {
		return DeviceName(name, type(), stringprintf("%d", unit()));
	}
}
long	ConfigurationTable::key2id(const ConfigurationKey& key) {
    std::list<long>	ids = selectids(condition(key));
    if (ids.size() != 1) {
        std::string	msg = stringprintf("%s not found",
                                       key.toString().c_str());
        throw NoSuchEntry(msg);
    }
    return *ids.begin();
}
static std::string	xms(double value, const char separator) {
	int	sign = (value >= 0) ? 1 : -1;
	value = fabs(value);
	int	X = floor(value);
	value = 60 * (value - X);
	int	M = floor(value);
	double	S = 60 * (value - M);
	return stringprintf("%c%02d%c%02d%c%06.3f", (sign < 0) ? '-' : '+',
		X, separator, M, separator, S);
}
/**
 * \brief run method
 */
void	ThreadCcd::run0() {
	try {
		this->run();
	} catch (const std::exception& x) {
		std::string msg = stringprintf("run() terminated by %s: %s",
			astro::demangle(typeid(x).name()).c_str(), x.what());
	} catch (...) {
	}
	_running = false;
}
/**
 * \brief find a parameter iterator
 *
 * This is a common code in many methods below, so it makes sense to
 * consolidate it into a single function
 */
Device::parametermap_t::const_iterator	Device::findParameter(
						const std::string& name) const {
	parametermap_t::const_iterator	result = _parameters.find(name);
	if (result == _parameters.end()) {
		std::string	msg = stringprintf("no parameter named '%s'",
			name.c_str());
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}
	return result;
}
/**
 * \brief trampoline function to start the run function of the class
 */
static void	*asi_main(void *parameter) {
	AsiGuidePort	*port = (AsiGuidePort *)parameter;
	std::string	portname = port->name();
	try {
		port->run();
	} catch (const std::exception& x) {
		std::string	msg = stringprintf("guider port %s failed: %s",
			portname.c_str(), x.what());
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		return NULL;
	} catch (...) {
		std::string	msg = stringprintf("guideport %s thread "
			"failed (unknown exception", portname.c_str());
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		return NULL;
	}
	debug(LOG_DEBUG, DEBUG_LOG, 0, "%s thread terminates",
		portname.c_str());
	return parameter;
}
/**
 * \brief Retrieve calibration ids for a selected guider
 */
std::list<long>	CalibrationTable::selectids(
	const GuiderDescriptor& guiderdescriptor) {
	std::string	condition = stringprintf(
		"instrument = '%s' and ccd = '%s' and controldevice = '%s' "
		"order by whenstarted",
		guiderdescriptor.instrument().c_str(),
		guiderdescriptor.ccd().c_str(),
		guiderdescriptor.guideport().c_str());
	debug(LOG_DEBUG, DEBUG_LOG, 0, "condition for calibrations: %s",
		condition.c_str());	
	return selectids(condition);
}
/**
 * \brief Convert the Instrument to a string version
 */
std::string	Instrument::toString() const {
	std::ostringstream	out;
	out << stringprintf("%-16.16s ", _name.c_str());
	std::list<DeviceName::device_type>      types = component_types();
	for (auto ptr = types.begin(); ptr != types.end(); ptr++) {
		if (ptr != types.begin()) {
			out << ",";
		}
		out << InstrumentComponentTableAdapter::type(*ptr);
	}
	return out.str();
}
DeviceName::device_type	DeviceName::string2type(const std::string& name) {
	for (int i = 0; i < Ntypes; i++) {
		if (typenames[i] == name) {
			debug(LOG_DEBUG, DEBUG_LOG, 0, "type %s mapped to %d",
				name.c_str(), i);
			return typecode[i];
		}
	}
	std::string	msg = stringprintf("type '%s' not found", name.c_str());
	debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
	throw std::runtime_error(msg);
}