/** * This method returns the MULTRUN command's acknowledge time. Each frame in the MULTRUN takes the * exposure time plus the status's max readout time plus the default acknowledge time to complete. * The default acknowledge time allows time to setup the camera, get information about the * telescope and save the frame to disk. This method returns the time for the first frame in the * MULTRUN only, as a MULTRUN_ACK message is returned to the client for each frame taken. * * @param command The command instance we are implementing. * @return An instance of ACK with the timeToComplete set. * @see #serverConnectionThread * @see #status * @see ngat.message.base.ACK#setTimeToComplete * @see LOTUSTCPServerConnectionThread#getDefaultAcknowledgeTime * @see MULTRUN#getExposureTime * @see MULTRUN#getNumberExposures */ public ACK calculateAcknowledgeTime(COMMAND command) { MULTRUN multRunCommand = (MULTRUN) command; ACK acknowledge = null; acknowledge = new ACK(command.getId()); acknowledge.setTimeToComplete( multRunCommand.getExposureTime() + serverConnectionThread.getDefaultAcknowledgeTime()); return acknowledge; }
/** * This method implements the MULTRUN command. * * <ul> * <li>We initialise exposure status variables * (<b>setExposureCount</b>/<b>setExposureNumber</b>/ <b>setExposureLength</b>). * <li>It moves the fold mirror to the correct location (<b>moveFold</b>). * <li>We setup the OBSTYPE and configure the fitsFilename instance based on whether we are * doing an exposure or standard. * <li>For each exposure we do the following: * <ul> * <li>We call <b>clearFitsHeaders</b> to reset the FITS headers information. * <li>We call <b>setFitsHeaders</b> to set FITS header data based on the current config. * <li>Calls <b>getFitsHeadersFromISS</b> to get FITS headers (incorporating the latest * offset) from the ISS. * <li>Adds the returned FITS headers to lotusFitsHeader. * <li>We call fitsFilename to generate a FITS filename to save data into, a create a * leafFilename fromthis to send to the INDI server. * <li>We call <b>createLockFile</b> to create a lock file. * <li>We call <b>ccd.expose</b> to do the exposure and save it in the specified filename. * <li>We call <b>lotusFitsHeader.writeFitsHeader</b> to append the constructed FITS * headers to the INDI generated FITS file. * <li>We call <b>deleteLockFile</b> to delete the previously created lock file. * </ul> * <li>We set up the return values to return to the client. * </ul> * * The resultant filenames or the relevant error code is put into the an object of class * MULTRUN_DONE and returned. During execution of these operations the abort flag is tested to see * if we need to stop the implementation of this command. * * @see #sendACK * @see #testAbort * @see #moveFold * @see #clearFitsHeaders * @see #setFitsHeaders * @see #getFitsHeadersFromISS * @see #lotus * @see #ccd * @see #lotusFitsHeader * @see LOTUS#log * @see LOTUS#error * @see LOTUS#getFitsFilename * @see LOTUSStatus#setCurrentMode * @see LOTUSStatus#setExposureCount * @see LOTUSStatus#setExposureNumber * @see LOTUSStatus#setExposureLength * @see LOTUSStatus#setExposureStartTime * @see FITSImplementation#createLockFile * @see FITSImplementation#deleteLockFile * @see ngat.lotus.ccd.StarlightExpressTriusSX35#expose * @see ngat.fits.FitsFilename#nextMultRunNumber * @see ngat.fits.FitsFilename#setExposureCode * @see ngat.fits.FitsFilename#nextRunNumber * @see ngat.fits.FitsFilename#getFilename * @see ngat.fits.FitsHeader#writeFitsHeader */ public COMMAND_DONE processCommand(COMMAND command) { MULTRUN multRunCommand = (MULTRUN) command; MULTRUN_DP_ACK multRunDpAck = null; MULTRUN_DONE multRunDone = new MULTRUN_DONE(command.getId()); FitsFilename fitsFilename = null; File fitsFile = null; String obsType = null; String filename = null; String leafname = null; double exposureLengthSeconds; int index; boolean retval = false; boolean fitsFilenameRename; boolean done; lotus.log( Logging.VERBOSITY_TERSE, this.getClass().getName() + ":processCommand:Starting MULTRUN with exposure length " + multRunCommand.getExposureTime() + " ms and number of exposures " + multRunCommand.getNumberExposures() + "."); if (testAbort(multRunCommand, multRunDone) == true) return multRunDone; // send an initiali ACK, actually getDefaultAcknowledgeTime long if (sendACK(multRunCommand, multRunDone, 0) == false) return multRunDone; // setup exposure status. status.setExposureCount(multRunCommand.getNumberExposures()); status.setExposureNumber(0); status.setExposureLength(multRunCommand.getExposureTime()); status.setCurrentMode(GET_STATUS_DONE.MODE_IDLE); // increment multrun number fitsFilename = lotus.getFitsFilename(); fitsFilename.nextMultRunNumber(); // move the fold mirror to the correct location if (moveFold(multRunCommand, multRunDone) == false) return multRunDone; if (testAbort(multRunCommand, multRunDone) == true) return multRunDone; try { if (multRunCommand.getStandard()) { obsType = FitsHeaderDefaults.OBSTYPE_VALUE_STANDARD; fitsFilename.setExposureCode(FitsFilename.EXPOSURE_CODE_STANDARD); } else { obsType = FitsHeaderDefaults.OBSTYPE_VALUE_EXPOSURE; fitsFilename.setExposureCode(FitsFilename.EXPOSURE_CODE_EXPOSURE); } } catch (Exception e) { lotus.error(this.getClass().getName() + ":processCommand:Failed to set Exposure Code:", e); multRunDone.setErrorNum(LOTUSConstants.LOTUS_ERROR_CODE_BASE + 1203); multRunDone.setErrorString("processCommand:Failed to set Exposure Code:" + e); multRunDone.setSuccessful(false); return multRunDone; } // configure the array exposureLengthSeconds = ((double) (multRunCommand.getExposureTime()) / 1000.0); // send an ACK, actually getDefaultAcknowledgeTime long if (sendACK(multRunCommand, multRunDone, 0) == false) return multRunDone; if (testAbort(multRunCommand, multRunDone) == true) return multRunDone; // do exposures index = 0; retval = true; while (retval && (index < multRunCommand.getNumberExposures())) { // send an ACK, actually at least one exposure length +readout long // diddly 4000 if (sendACK(multRunCommand, multRunDone, multRunCommand.getExposureTime() + 4000) == false) { lotus.log( Logging.VERBOSITY_VERY_VERBOSE, this.getClass().getName() + ":processCommand:sendACK failed for index " + index + "."); return multRunDone; } if (testAbort(multRunCommand, multRunDone) == true) { status.setCurrentMode(GET_STATUS_DONE.MODE_IDLE); return multRunDone; } lotus.log( Logging.VERBOSITY_INTERMEDIATE, this.getClass().getName() + ":processCommand:Starting exposure " + index + " of length " + exposureLengthSeconds + "s."); lotus.log( Logging.VERBOSITY_INTERMEDIATE, this.getClass().getName() + ":processCommand:Clear FITS headers."); clearFitsHeaders(); // set FITS header if (setFitsHeaders( multRunCommand, multRunDone, obsType, multRunCommand.getExposureTime(), multRunCommand.getNumberExposures()) == false) { lotus.log( Logging.VERBOSITY_VERY_VERBOSE, this.getClass().getName() + ":processCommand:setFitsHeaders failed for index " + index + "."); return multRunDone; } // get FITS headers from ISS if (getFitsHeadersFromISS(multRunCommand, multRunDone) == false) { lotus.log( Logging.VERBOSITY_VERY_VERBOSE, this.getClass().getName() + ":processCommand:getFitsHeadersFromISS failed for index " + index + "."); return multRunDone; } try { // increment run number in Multrun fitsFilename.nextRunNumber(); // get filenane filename = fitsFilename.getFilename(); // get leaf name of fits filename fitsFile = new File(filename); leafname = fitsFile.getName(); // now remove '.fits' as INDI driver does not want this in the filename leafname leafname = leafname.substring(0, leafname.lastIndexOf('.')); // create lock file createLockFile(); } catch (Exception e) { deleteLockFile(); lotus.error( this.getClass().getName() + ":processCommand:Processing FITS filename failed:", e); multRunDone.setErrorNum(LOTUSConstants.LOTUS_ERROR_CODE_BASE + 1204); multRunDone.setErrorString("processCommand:Processing FITS filename failed:" + e); multRunDone.setSuccessful(false); return multRunDone; } if (testAbort(multRunCommand, multRunDone) == true) { deleteLockFile(); status.setCurrentMode(GET_STATUS_DONE.MODE_IDLE); return multRunDone; } // take exposure lotus.log( Logging.VERBOSITY_INTERMEDIATE, this.getClass().getName() + ":processCommand:Exposing CCD for " + exposureLengthSeconds + " seconds."); status.setExposureStartTime(System.currentTimeMillis()); try { status.setCurrentMode(GET_STATUS_DONE.MODE_EXPOSING); ccd.expose(exposureLengthSeconds, leafname); status.setCurrentMode(GET_STATUS_DONE.MODE_READING_OUT); } catch (Exception e) { status.setCurrentMode(GET_STATUS_DONE.MODE_IDLE); deleteLockFile(); lotus.error(this.getClass().getName() + ":processCommand:Taking exposure failed:", e); multRunDone.setErrorNum(LOTUSConstants.LOTUS_ERROR_CODE_BASE + 1201); multRunDone.setErrorString("processCommand:Taking exposure failed:" + e); multRunDone.setSuccessful(false); return multRunDone; } if (testAbort(multRunCommand, multRunDone) == true) { status.setCurrentMode(GET_STATUS_DONE.MODE_IDLE); deleteLockFile(); return multRunDone; } // update FITS headers needing timestamp information if (setFitsHeaderTimestamps(multRunCommand, multRunDone) == false) { deleteLockFile(); lotus.log( Logging.VERBOSITY_VERY_VERBOSE, this.getClass().getName() + ":processCommand:setFitsHeaderTimestamps failed for index " + index + "."); return multRunDone; } // append FITS headers to created FITS image try { lotusFitsHeader.writeFitsHeader(filename); } catch (Exception e) { status.setCurrentMode(GET_STATUS_DONE.MODE_IDLE); deleteLockFile(); lotus.error( this.getClass().getName() + ":processCommand:Adding FITS headers to " + filename + " failed:", e); multRunDone.setErrorNum(LOTUSConstants.LOTUS_ERROR_CODE_BASE + 1205); multRunDone.setErrorString( "processCommand:Adding FITS headers to " + filename + " failed:" + e); multRunDone.setSuccessful(false); return multRunDone; } // delete lock file deleteLockFile(); // flip images? // increment exposure number status.setExposureNumber(index + 1); // test whether an abort has occured. if (testAbort(multRunCommand, multRunDone) == true) { retval = false; } index++; } // end while status.setCurrentMode(GET_STATUS_DONE.MODE_IDLE); // no pipeline processing, set return value to something bland. // set filename to last filename exposed. multRunDone.setFilename(filename); multRunDone.setCounts(0.0f); multRunDone.setSeeing(0.0f); multRunDone.setXpix(0.0f); multRunDone.setYpix(0.0f); multRunDone.setPhotometricity(0.0f); multRunDone.setSkyBrightness(0.0f); multRunDone.setSaturation(false); // if a failure occurs, return now if (!retval) return multRunDone; // setup return values. // setCounts,setFilename,setSeeing,setXpix,setYpix // setPhotometricity, setSkyBrightness, setSaturation set by reduceExpose for last image // reduced. multRunDone.setErrorNum(LOTUSConstants.LOTUS_ERROR_CODE_NO_ERROR); multRunDone.setErrorString(""); multRunDone.setSuccessful(true); // return done object. lotus.log( Logging.VERBOSITY_VERY_TERSE, this.getClass().getName() + ":processCommand:MULTRUN command completed."); return multRunDone; }