/** * \brief Start an exposure on the M26C camera * * \param exposure exposure structure for the exposure to perform */ void SxCcdM26C::startExposure0(const Exposure& exposure) { debug(LOG_DEBUG, DEBUG_LOG, 0, "exposure %s requested", exposure.toString().c_str()); // remember the exposre, we need it for the second field for the // case where we do two fields one after the other this->exposure = symmetrize(exposure); m26c = m26cExposure(); // compute a better request for the M26C camera exposeField(0); timer.start(); // we are now in exposing state state = Exposure::exposing; }
/** * \brief Start an exposure on the M26C camera * * \param exposure exposure structure for the exposure to perform */ void SxCcdM26C::startExposure0(const Exposure& exposure) { debug(LOG_DEBUG, DEBUG_LOG, 0, "exposure %s requested", exposure.toString().c_str()); // remember the exposure, we need it for the second field for the // case where we do two fields one after the other this->exposure = symmetrize(exposure); // compute a better request for the M26C camera m26c = m26cExposure(); // start the exposure if (!camera.reserve("exposure M26C", 1000)) { std::string msg("cannot reserve camera"); debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str()); throw std::runtime_error(msg); } exposeField(0); timer.start(); // we are now in exposing state state(CcdState::exposing); }
/** * \brief Retrieve an image from the caemra * * This method completes the exposure on the main ccd and reads the field. * Depending on the exposure time, it then either starts a new exposure * (for short exposures, because the second field would otherwise be too * different), or reads out the already exposed second field (for long * exposures). In the latter case, the first field is rescaled to account * for the different exposure time. */ void SxCcdM26C::getImage0() { debug(LOG_DEBUG, DEBUG_LOG, 0, "get an image from the camera"); // read the right number of pixels from the IN endpoint Field *field0 = readField(); debug(LOG_DEBUG, DEBUG_LOG, 0, "field 0 transferred"); if (debuglevel == LOG_DEBUG) { debug(LOG_DEBUG, DEBUG_LOG, 0, "writing field 0"); std::ofstream out("field0.raw", std::ofstream::binary); out << *field0; out.close(); } // for long exposures, we just read the second field. Field *field1 = NULL; if (exposure.exposuretime() > EXPOSURE_FIELD_CUTOVER) { debug(LOG_DEBUG, DEBUG_LOG, 0, "request second field 1"); timer.end(); requestField(1); } else { debug(LOG_DEBUG, DEBUG_LOG, 0, "expose second field 1"); exposeField(1); } // read the second field debug(LOG_DEBUG, DEBUG_LOG, 0, "read field 1"); field1 = readField(); if (debuglevel == LOG_DEBUG) { debug(LOG_DEBUG, DEBUG_LOG, 0, "writing field 1"); std::ofstream out("field1.raw", std::ofstream::binary); out << *field1; out.close(); } // rescale the first field, if we did only one exposure if (exposure.exposuretime() > EXPOSURE_FIELD_CUTOVER) { //double deadtime = 3.37; // exposuretime = 11 //double deadtime = 3.99; // exposuretime = 20 double deadtime = 1.2; double scalefactor = (timer.elapsed() - deadtime) / exposure.exposuretime(); debug(LOG_DEBUG, DEBUG_LOG, 0, "scalefactor = %f", scalefactor); // rescale the field. We have to multiply the first field // with the scaling factor, because of overflows if (scalefactor > 0) { field0->rescale(scalefactor); } else { debug(LOG_DEBUG, DEBUG_LOG, 0, "no rescaling"); } //field0->rescale(1.1283); } // prepare a new image, this now needs binned pixels Image<unsigned short> *_image = new Image<unsigned short>( exposure.frame().size() / exposure.mode()); _image->setOrigin(exposure.frame().origin()); _image->setMosaicType(MosaicType::BAYER_RGGB); // now we have to demultiplex the two fields debug(LOG_DEBUG, DEBUG_LOG, 0, "demultiplex the fields"); if (1 == exposure.mode().x()) { DemuxerUnbinned demuxer; demuxer(*_image, *field0, *field1); } else { DemuxerBinned demuxer; demuxer(*_image, *field0, *field1); } // remove the data delete field0; delete field1; // return the demultiplexed image image = ImagePtr(_image); state = Exposure::exposed; }