samedi 27 juillet 2019

Semi-automated Be star spectra acquisition

I have been acquiring Be star spectra in a semi-automated way using PRISM v10 and its scripting capabilities. Here are some more details on how this works.


Main equipment is a C11 telescope on a Losmandy Titan mount with Gemini II controler. I recently updated it from Gemini I (and from origonal motors to Maxxon ones) - a huge improvement in pointing accuacy.
I connect in PRISM using ASCOM driver but connect to POTH (Ascom hub) from PRISM and setup the Gemini.Net within POTH; this seems more stable and works fine.

Here are my parameters for the Gemini.Net:


Here are some function I use in the script to control telescope:
   CONNECT_OBSERVATORY Valid : connect telescope/dome
   STOPTELESCOPE : stop tracking
   CLOSE_TELESCOPE_DEVICES


The telescope is installed in a 2.7m Pulsar dome; I have a Dome Tracker to control the dome and PRISM interface with it directly.

I use OPEN_DOME and CLOSE_DOME in my script. I also use "DOME_SET_CONTROL 1 1" to ensure the dome is always in synch with the telescope.


I have two GemBird computer controled power plugs so I can switch equipment ON/OFF by using the Power Manager software that comes with those; I just run as an external program in my script, a nice PRISM feature; for exemple:
   EXECEXTERNAL "C:\Program Files\Power Manager\pm.exe" "-on -Device3 -DomeTracker"

For the (echelle, fiber fed) spectrograph, I use a Velmann board that is handled in PRISM as a switch. Here are the functions I use for this:
   Switchdesired=1
   GETSWITCH Switchdesired nbSwitches ArrayName ArrayState
   SETSWITCH Port1 ON


The script starts with a begining sequence that wait for the Sun's elevation; when right, it connects to the equipment, cool off the main CCD camera, runs the calibration and then starts the observing sequence. At the end, I just close equipment and dome.


To find my next target (which is repeated all night), I use a catalog of Be stars that I create in an Open Office Calc. It uses a robot file created every night in BESS database (through ARASBeAm website) that list for each Be star when it was last observed and what is the expected observing period (usually 365 days). I calculate from this a BESS priority but add my own priority too.

The catalog only list ~200 objects which are bright and isolated as my strategy is to center the brightest object in the guiding camera.

The guiding camera is a Zwo ASI174MM (a recent update from my old Atik Titan which I had lot of trouble with specially with latest Atik drivers). The field of view is great and it works very well.

To find the brightest object, I acquire an image, save it in FITS and JPEG format, bin the image 4x4 and look for brightest star:
    StartExposure_EX 1 GExpTimeChamp
    WaitForEndExposure_EX 1
    GetLastImageExposure_EX 1 ImgChampToCenter
    sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+"_tocenter.fits"
    SAVEFIT ImgChampToCenter sFullPath$
    sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+"_tocenter.jpg"
    SAVEJPG ImgChampToCenter sFullPath$
    BinX=4
    BinY=BinX
    BINNINGREDUCE  ImgChampToCenter  BinX  BinY
    BRIGHTEST_STAR ImgChampToCenter MinDynamiqueAutoguidage MaxDynamique MaxOmC PSFMin DemLargFenCentro ZoneRecherche XGuideCentro YGuideCentro


I had hard time to find the right parameters. I bin so the star are not too large and so the running time is acceptable. The MaxOmC parameter can be found when doing a centroid on an image; having it too low reject some actual stars; I use 2000 as a value now and it works.


To center the brightest star, I calculate the shift in RA/DEC. If it is close enough to the fiber ole I just start the autoguiding but if not I recalculate RA/DEC so repointing the target to recenter it.
    MOVETELESCOPE AlphaNew DeltaNew
    WAITFORENDMOVETELESCOPE

There seems to be a bug in Gemini.Net ASCOM because if I ask for a GoTo to the same position I ask before, it fails and goes wild. SO I have a two steps approach by pointing a position close to my target and do a second GoTo after. Even for recentering the object I am doing this two steps approach and it works.




Autoguiding is run with a single function, autoguiding needs to be predefined before in PRISM:
    STARTGUIDECONSIGNE NumCam CCDNum GExpTimeBis DelayACQSec WindowSize CentroSize StarThresADU AgressRA AgressDEC RaMin RaMax DecMin DecMax Backlash CurrentDEC AlarmEnabled DeltaMoveFashion GuidePosX GuidePosY SaveImagettes DirSaveImg$ AllFrame WindowAllFrame Valid message$

Note that I am checking the hour angle, so the distance to meridian in order to stop my acquisition sequence before I cross the meridian too far.

I also run some statistics on each raw spectra image to avoid saturation and allow night to night comparison. Those are displayed and saved in a log file as well.

At the end of the target acquisition, I recalibrate the telescope on the object coordinates as it moved during the autoguiding sequence:
    CALIBRATE_TELESCOPE alpha delta





Here is a link to a Youtube video taken during a full session. No comment but you can follow the observation as it progress...






Here is my current code which you can of course freely use for your own private use:


/////////////////////////////////////////////////////////////////////////////////
//                                                                                                                                                                             //
//                                   OTZ_Auto - Script to observe automatically (c) Olivier Thizy                              //
//                                                                                                                                                                             //
/////////////////////////////////////////////////////////////////////////////////
//
// Some specificities to equipment used:
// -Losmandy Titan mount (upgraded witrh Maxxon motors & Germini 2 in 2019)
//   Connected through Gemini.Net + POTH (mandatory for PRISM to work properly) with 2.5sec regular readout (idem)
// -echelle spectrograph with Velmann board to control calibration lamps
// -observing bright Be star as primary (only!) focus
// -Atik 460ex for spectra acquisition
// -Zwo ASI174MM (was Atik Titan) for guiding
// -Dome (controled by Dome Tracker)
// -RoboFocus
//
// Brief description of the algorythm:
//  -I wait for the Sun to be below some limit (bsed on experience)
//  -First I create my night's directory, copy/paste my usual CALIB files (master darks, current version of script...).
//  -I connect my equipment (note that I usually switch my Power Manager ON manually because it's not stable,
//    I also connect my cameras and my telescope manually because PRISM/ASCOM seems to be unstable there.
//  -I lower the temperature of the main camera and wait for the Sun to be at a certain elevation.
//  -I acquire (if necessary) my calibration frames for the night: a long serie of Tungsten for the blaze of the echelle spectrum,
//    three LED to get the geometry of the echelle orders and three Thorium-Argon for wavelength calibration
//  -I wait for th Sun's elevation to be at the level that allow observation to start
//  -I load my catalog file which is created by an Excel spreadsheet where I import BeSS robot file;
//   in a nutshell, the catalog file lists my ~200 Be stars targets with catalog name for PRISM to use, magnitude
//   (used to calculate the guiding exposure time), the BeSS priority based on required observing period and last observation date
//   (I also take into account if I have observed it myself as BeSS takes time to be validated/updated sometimes),
//   a bonus priority for my favorite targets or current hot targets, individual exposure time and number of exposure to acquire.
//  -Then I enter a loop for the night:
//    >based on telescope position, and excluding targets below minimum elevation (40°), crossing the meridien  at mid exposure
//     (I always observe in the East part of the sky) and below a DEC limit (just because my pointing accuracy there is lower),
//      I select my next target (of course, one that has not been observed that night so far)
//    >I point the telescope to the target, wait for the dome, center target (brightest star) and then start the autoguiding
//     (if no star is found, I try an astrometry and if not possible then I wait 5min with telescope tracking stopped)
//    >then I start the exposure until the target is crossing the meridian or I reach the required number of exposures
//      or if the Sun elevation if above the limit to end the observations --> then I go to the end of Session
//    >and I loop to go to the next target...
//  -End of Session: I stop telescope, I close the dome, I increase the temperature of the main camera, I close all equipment
//
// After a session, I reduce all my spectra using ISIS, the clean up all the intermediate files, create an archive and a ZIP file with
// all my spectra to upload them in BeSS database... and I wait until the sky is clear for next session!


// BUGS / ROBUSTNESS (TO DO)
// ------------------
// -improve mechanical holder for the dome sensor (ie: spring to be improved)
// -Goto with WaitForDome option failed sometimes: removed from script for now / to be checked
// -replace USB by LAN gembird: hardware ready when needed, not critical for now
// -pb with telescope connexion (hardware?): done manually for now, to check again ?
// -pb with Zwo ASI that sometimes freeze (USB link to improve?)
//
// WEATHER MANAGEMENT (TO DO)
// -------------------
// -rain detection -> wiring to dome tracker + software test to stop telescope & close everything else
// -calibrate Sentinel cloud sensor: seems very difficult to find the righ parameters, need more work on this
// -wait for good weather: tested but failed; need to be improved
// -check weather: pause
// -multiple pause: close equipment
// -sentinel relay script activation
//
// IMPROVEMENTS (TO DO)
// -------------
// -when a target not found, skip it (could try later? limit to 3 retries total?)
// -add list of targets done during last few nights to add to BeSS priority calculation (to limit same target several nights)
// -automated ISIS data reduction with Actiona external tool
// -at the end creates a simple web page with guiding image, last ARASBeAm spectrum graph and our Halpha graph
// -catalog of bright isolated stars or astrometry on the field
// -goto with star hopping or astrometry on the field
// -improve simulator mode to take into account elevation & distance to meridian at time of observation (targets.txt mode)
// -add management of star to Synch at the end of a session to "park" scope
// -split start & calib & directory setup
// -search for object$ to avoid local/global variables
// -add the ability to do calibration at the end in case weather is bad at the beginning of the session
// -check disc space at the beginning
// -add to the ARASBeAm priority calculation my own observations (not validated in BeSS yet) to avoid always doing the same targets
// -add fainter target with an astrometry mode
//
// REVISION HISTORY (WHAT HAS BEEN DONE)
// ----------------
// -05/08/2018: first "stable version", target list inside script, some bugs (telescope connexion, USB Gembird, first autoguiding).
//    Lack weather management, good target catalog, star hopping method for large GoTo, etc... some comments in french.
//    Based on brightest star in the field, very specific to my own equipment. 60 Be stars spectra (Halpha) acquired so far with the script.
// -15/08/2018: add printed info when star lower than HauteurMin; read targets from an external text file; simulation & total exposure time calculation
//    Some functions to read a Be star catalog with BeSS priorities, my own priorities & calculate a weight to sort stars by interest. Seems to work ok.
// -19/08/2018: fix of the displayed hor angle (calculated on target and not from telescope position)
// -09/09/2018: automatic check if calibration is done; simulation removed (always done, user can stop script if he wants),
//   calibration, goTo and download time added in time for session calculation, directory naming/creation done at beginning
// -15/09/2018: first test of automatic target finding based on catalog file (BeSS priorities still manual),
//    elevation of the Sun calculated for end of acquisition (not begining), if object$ is not recognize: skip target,
//    automatic guiding exposure based on Vmag, automatic scheduling based on priority & time allocation
// -17/09/2018: correct end of night bug with Sun's elevation calculation on limit hour angle calculation
// -27/09/2018: fixed starDeltaRA calculation when telescope close to 24h, fixed AngleHor calculation in CheckStarCatalogForVisibility
// -07/10/2018: fixed end of observersion date and add DateFrac test (Sun elevation after midnight!)
// -09/10/2018: improve stop observing time Vs begin time to avoid trying to observe too late...
// -23/10/2018: limites après méridien fortement diminuée pour éviter les pertes de GoTo
// -15/02/2019: alphaplus=alpha+0.005 (au lieu de -0.005 avant) pour améliorer le pointage
// -02/06/2019: modifications following Gemini 2 upgrade; no pointing model in Gemioni 2 or PRISM for now...
// -03/06/2019: adding AskForManualAutoGuiding option as it doens't work in PRISM with new ATIK drivers !!!
//   Removing of recentering of the brightest object in the field as it doesn't work anymore in PRISM with latest update :-(
// -16/06/2019: replacing Atik Titan by Zwo ASI 178MC guiding camera
// -22/06/2019: replacing guiding camera by a Zwo ASI 174MM, added several comments & cleaning the script  file
// -23/06/2019: added SHIFT_TELESCOPE to recenter the target and it works!!!
// -24/06/2019: added a two steps approach for GoTo & reecentering (due to a bug in PRISM/POTH/Gemini.Net chain somewhere...)
//   Add couple of log files with stats
//  -30/06/2019: switched to OTH_Catalog2 with MyName added (target list name with spaces). Checked several bugs that I can remove:
//   >sometimes fails at first autoguiding, root cause not found yet, didn't happend with Zwo ASI174 so ok...
//   >end of night, dome disconnected? didn't happend for long time now? seems OK...
//   >at end of the night it doesn't stop early enough, need to revisit how scheduler works: better since early 2019 - ok...
//   >sometimes it tries to go to a target but it is too close to meridian, loosing 5min each time (improved in eartly 2019) - ok...
//   >stop telescope tracking while waiting for next target, done ok
//  -07/07/2019: added an astrometry search in case target is not found (to be improved to gain time)
//   >catalog file read for each target (so can be modified even when script is running)
//    >if star is already close to the fiber hole, no need to recenter it so skiping it then
//  -13/07/2019:  BINNINGREDUCE (instead of SCALE) 4x4 for BRIGHTEST_STAR
//    >add FIND_ALLSKY_POSITION (with binning 2x2) when star not found
//  -14/07/2019: Move astrometry search at beginning of each target GoTo
//  -17/07/2019: move back to brightest star in the field as astrometry isn't reliable yet... Pb with Gemini.Net more than PRISM scripts at the moment...
//
//
/////////////////////////////////////////////////////////////////////////////////


print "OTZ_Auto: (semi)automatic observation script (c) Olivier Thizy"
print "Version of 17/07/2019"


// Key debug/temporary parameters to control manual interventions...
// Note: for full automated observations all parameters should be to FALSE except ExposureCloudFactor which should be 1.0 (1.6 works fine too)
TRUE=1
FALSE=0
//    ExposureCloudFactor: set to 1.4 but increase up to 3.0 if sky is cloudy (will increase guiding image exposure time)
ExposureCloudFactor=2.0
//     CheckIfPowerManagerIsOK: set to TRUE to make a double check of the Power Manager as USB isn't always working properly
CheckIfPowerManagerIsOK=FALSE
//    ConnectTelescopeManually: set to TRUE if you want to connect manually telescope/equipment in prism
ConnectTelescopeManually=FALSE
//     RequestManualInitialSynch: set to TRUE if you want to manually synch telescope to first star
RequestManualInitialSynch=FALSE
//    UseTargetFile: set to TRUE to use targets.txt file for the targets; otherwise script will use catalog to find automatically next target
UseTargetFile=FALSE
//    SkipCalibration: set to TRUE if you do not want to look for calibration frames (and acquire them), alternative is to have a dummy "ref_thor-3.fits" file
SkipCalibration=FALSE
//    AskForManualAutoGuiding: set to TRUE if you want to start & end autoguiding manually
AskForManualAutoGuiding=FALSE
//    Allow for astrometry calibration to reynch in case star not found ?
AllowAstrometry=FALSE
//     OpenDomeManually: Set to TRUE if you want to open dome manually (to make sure weather is OK when ready for observations)
OpenDomeManually=TRUE


//
// General parameters
//
TWOPI=2*PI
// do not point telescope past meridian
AngleHorMin=0
// minimum elevation = do not observe below... (in °); usually 40° for me
HauteurMin=45
// Maximum distance for next target (in degrees)
MaximumStarDistanceToTelescope=45.0
// Maximum DEC for targets
MaximumStarDEC=48
// parameters for guiding camera ASI174MM:
// fiber position
GuidePosX=897.5
GuidePosY=541.7
// image will be reduce by 4 in each axis to do the search for brightest star (speed up processing time)
Facteur=0.25
GuidePosXFact=897.5*Facteur
GuidePosYFact=541.7*Facteur
// scale for the pixel size, important to adjust the RA/DEC shift to center target to the fiber tip
EchelleXFact=0.46311/Facteur
EchelleYFact=EchelleXFact
EchelleXFactAstro=0.46311*2
EchelleYFactAstro=EchelleXFactAstro
MinDynamiqueAutoguidage=700
MaxDynamique=65000
// max Observed Minus Calculated, see result when doing manual centroid, usually MaxOMC=2000 works better than 900...
MaxOmC=2000
PSFMin=2
// not sure if I need to *Facteur there or not...
DemLargFenCentro=28
ZoneRecherche=DemLargFenCentro+1
// for ASI174MM in full frame bin 1x1  (image : 1936x1216)
GuidingExpFactor=2
GuidingDelayACQSec=10
GuidingCentroSize=25
GuidingStarThresADU=100
GuideXMax_2=200
// For astrometry search...
GExpTimeAstrometryChamp=45000
CatalogAst$="UCAC 2/3/4"
ChemCatalogAst$="D:\UCAC4\u4b\"
MaxStarImg=40
MaxStarCat=120
FieldAllSky=1

// For Atik 460ex camera, cooling in 16 minutes to -10°C (winter) or 0°C (summer) seems enough
minutestogodowntotemp=16
Detectortemperature=0.0
// Elevation of the sun at which we start the instrumentation (degrees converted to radians)
// I usually start equipment when Sun is below 0°, start calibration when below 4° in order to start observing when below -8°
Summer=TRUE
Season=Summer
if Season=Summer then
    elevsunstartinitnight_Deg=-2.0
    elevsunstartbegnight_Deg=-5.0
    elevsunstartobservations_Deg=-8.0
    elevsunstopobservations_Deg=-11.0
    elevsunstopgoto_Deg=-13.0
else
    elevsunstartinitnight_Deg=-1.0
    elevsunstartbegnight_Deg=-4.0
    elevsunstartobservations_Deg=-9.0
    elevsunstopobservations_Deg=-9.0
    elevsunstopgoto_Deg=-11.0
endif
// CCD numbers
GuidingCamNumber=1
AcqCamNumber=2
// difference between local time and UT
deltaUT=-1
// time (in milliseconds) to wait after GoTo so dome can be synch' with telescope
if AskForManualAutoGuiding=TRUE then
    WaitForDomeTime=5000
else
    WaitForDomeTime=90000
endif
// Sentinel weather station parameters
LimitTempCiel=-100.0
LimitMagnitudeCiel=-100.0
ValMinBelleMeteo=5
// Root directory for acquisition. Contains CALIB with catalog files & directory will be created there for each new night
//RootDirName$="D:\Acquisitions\"
RootDirName$="C:\Users\ObsBE\Documents\Acquisitions\"
// Catalog filenames
StarCatalogFileName$=RootDirName$+"CALIB\OTH_Catalog2.txt"
// Log file where exposure results will be added
ObjectLog$=RootDirName$+"CALIB\elog_objects.txt"
StatsLog$=RootDirName$+"CALIB\elog_stats.txt"



// GoTo TestCatalogFunctions:

// Check if calibration has been done already or not
GoSub CalculateNightDate:
File$=sDirSave$+"ref_thor-3.fits"
FileExists  File$  StartAndCalibDone

if UseTargetFile=TRUE then
    // Reading Target list
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Reading 'targets.txt' file"

    DirTargetList$="C:\Users\ObsBE\Documents\Acquisitions\CALIB\targets.txt"
    Open_FileTxt_For_Read ObjectTargetFile DirTargetList$

    NbTargets=1

    ReadFileTXT ObjectTargetFile Target[NbTargets]$

    LoopObjectTargetList:
    ENDOFFILE ObjectTargetFile resultat
    if resultat=FALSE then
        NbTargets=NbTargets+1
        ReadFileTXT ObjectTargetFile Target[NbTargets]$
        GoTo LoopObjectTargetList:
    EndIf

    // Simulation pf the session
    TotalExpTimeForTargets=0

    elevsunstartbegnight=elevsunstartbegnight_Deg/TODEG

    // Search for date/time Sun is ok to start observation...
    Step=0.002
    Now DateSessionWillBegin
    LoopSearchBegTime:
    GETRADECSUN  DateSessionWillBegin  AlphaS  DeltaS  sunelevation
    if sunelevation>elevsunstartbegnight
        DateSessionWillBegin=DateSessionWillBegin+Step
    else
        goTo EndLoopSearchBegTime:
    endif
    goTo LoopSearchBegTime:
    EndLoopSearchBegTime:

    for NumeroObject=1 to NbTargets
        Object$=Target[NumeroObject]$
        GoSub LookUpObject:
        // 240sec for GoTo sequence + 30sec par pose (download)
        TotalExpTimeForSession=TotalExpTimeForSession+240+(ExpSec+30)*NbExposure
        TotalExpTimeForTargets=TotalExpTimeForTargets+ExpSec*NbExposure
        Now Date
        Datetostr Date Date$
        print NumeroObject "; " Object$ "; " ExpSec "; " NbExposure
    next NumeroObject

    str TotalExpTimeForTargets TotalExpTimeForTargets$
    TotalExpTimeForTargetsMin=(TotalExpTimeForTargets/60)
    round TotalExpTimeForTargetsMin TotalExpTimeForTargetsMin
    str TotalExpTimeForTargetsMin TotalExpTimeForTargetsMin$
    TotalExpTimeForTargetsHours=(TotalExpTimeForTargets/3660)
    frac TotalExpTimeForTargetsHours TotalExpTimeForTargetsHoursM
    TotalExpTimeForTargetsHoursM=TotalExpTimeForTargetsHoursM*60
    round TotalExpTimeForTargetsHoursM TotalExpTimeForTargetsHoursM
    TotalExpTimeForTargetsHoursH=TotalExpTimeForTargetsHours-TotalExpTimeForTargetsHoursM/60
    round TotalExpTimeForTargetsHoursH TotalExpTimeForTargetsHoursH
    str TotalExpTimeForTargetsHoursH TotalExpTimeForTargetsHoursH$
    str TotalExpTimeForTargetsHoursM TotalExpTimeForTargetsHoursM$
    if TotalExpTimeForTargetsHoursM=0
        TotalExpTimeForTargetsHoursM$="00"
    endif
    if TotalExpTimeForTargetsHoursM<10
        TotalExpTimeForTargetsHoursM$="0"+TotalExpTimeForTargetsHoursM$
    endif

    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Total Exposure should be: " TotalExpTimeForTargets$ " sec., " TotalExpTimeForTargetsMin$ " min., " TotalExpTimeForTargetsHoursH$ "h" TotalExpTimeForTargetsHoursM$ "."

    str TotalExpTimeForSession TotalExpTimeForSession$
    TotalExpTimeForSessionMin=(TotalExpTimeForSession/60)
    round TotalExpTimeForSessionMin TotalExpTimeForSessionMin
    str TotalExpTimeForSessionMin TotalExpTimeForSessionMin$
    TotalExpTimeForSessionHours=(TotalExpTimeForSession/3660)
    frac TotalExpTimeForSessionHours TotalExpTimeForSessionHoursM
    TotalExpTimeForSessionHoursM=TotalExpTimeForSessionHoursM*60
    round TotalExpTimeForSessionHoursM TotalExpTimeForSessionHoursM
    TotalExpTimeForSessionHoursH=TotalExpTimeForSessionHours-TotalExpTimeForSessionHoursM/60
    round TotalExpTimeForSessionHoursH TotalExpTimeForSessionHoursH
    str TotalExpTimeForSessionHoursH TotalExpTimeForSessionHoursH$
    str TotalExpTimeForSessionHoursM TotalExpTimeForSessionHoursM$
    if TotalExpTimeForSessionHoursM=0
        TotalExpTimeForSessionHoursM$="00"
    endif
    if TotalExpTimeForSessionHoursM<10
        TotalExpTimeForSessionHoursM$="0"+TotalExpTimeForSessionHoursM$
    endif

    DateEndSession=DateSessionWillBegin+TotalExpTimeForSessionMin/(24*60)
    Datetostr DateSessionWillBegin DateSessionWillBegin$
    Datetostr DateEndSession DateEndSession$

    print "[" Date$ "] Total session should be: " TotalExpTimeForSession$ " sec., " TotalExpTimeForSessionMin$ " min., " TotalExpTimeForSessionHoursH$ "h" TotalExpTimeForSessionHoursM$ "."
    print "[" Date$ "] Session from " DateSessionWillBegin$ " to " DateEndSession$ " (UT)"


    Input "WAIT for you to press enter before continuing the script" Dummy$

endif

//
// START & CALIBRATION
//

if StartAndCalibDone=FALSE then
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Starting Calibration sequence"
    GoSub Start_and_Calib:
else
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Calibration sequence already done"
endif

Now Date
Datetostr Date Date$
print "[" Date$ "] Starting observing sequence"



// Just to test it...
//GoSub BoucleAttendBeauTemp:

    // Resynch telescope on delta Her
    if RequestManualInitialSynch=1 then
        Input "TEST: ensure telescope is synch (& focused ?) near to first target - then press ENTER" Dummy$
    else
        // Synch sequence for the beginning of the bight - todo
        // look for a bright star near telecope position and/or astrometry.net ?
    endif

if UseTargetFile=1 then
    for NumeroObject=1 to NbTargets
        Object$=Target[NumeroObject]$
        if NbExposure<>0 then
            GoSub TakeObject:
        endif
    next NumeroObject
else
    // Each target will be found with minimum elevation & far enough from meridian
    // using a score calculation based on distance to telescope, my own priority and BeSS priorities
    // BeSS: Be Star Spectra database
    NumeroObject=0

    LoopAcquisitionOfTargets:
        stoptelescope

        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Reading target star catalog"
        GoSub ReadStarCatalog:

        Now Date
        Datetostr Date Date$
        print "[" Date$ "] number of stars in the target list : " numberofstarsintargetlist


        // Check Sun elevation before continuing observing next target...
        GetStdrLongitude Longitude
        GetStdrLatitude Latitude

        elevsunstopgoto=elevsunstopgoto_Deg/TODEG

        Now Date
        GETRADECSUN  Date  AlphaS  DeltaS  sunelevation
        FRAC Date DateFrac
        if sunelevation>elevsunstopgoto
            if DateFrac<0.5
                Now Date
                Datetostr Date Date$
                print "[" Date$ "] Sun too high to continue observing"
                GoTo EndOfSession:
            endif
        endif

       
        // Reset sort order & look for next target (not done during the night and highest score)
        for Temp_i=1 to numberofstarsintargetlist
            sortIndex[Temp_i]=Temp_i
        next Temp_i

        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Calculating telescope distance for all star in catalog"
       
        GET_TELESCOPE_POSITION Alpha2000 Delta2000 Hauteur Azimuth AngleHor

        RARef=24.0*Alpha2000/(2.0*PI)
        DECRef=180*Delta2000/PI
       
        GoSub CalculateDistanceStarCatalogToRef:

        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Checking visibility for all stars in catalog"

        GoSub CheckStarCatalogForVisibility:

        // Need to add here a function to check when the target has been acquired (cf StatsLog$) to overwrite BeSS priority based on my own observation
       
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Sorting stars in catalog"

        GoSub SortStarCatalog:

        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Looking for next target..."

        GoSub CalculateNightDate:

        HasATargetBeenFound=0
        for Temp_i=1 to numberofstarsintargetlist
            Temp_j=SortIndex[Temp_i]
            Temp_Prio=SortCriteria[Temp_j]
           
//            print "Prio=" Temp_Prio " starname number : " Temp_i " is : " starFileName[Temp_j]$ " star RA in decimal : " starRA[Temp_j] " star Dec in decimal : " starDec[Temp_j] " Vmag=" starVMag[Temp_j] " Guiding Exp Time=" starGuideExposureSec[Temp_j] " BeSS=" starWeightBeSS[Temp_j] " MyPrio=" starWeightOTH[Temp_j] " Distance=" starWeightDistance[Temp_j]
            if Temp_Prio>0 then
                File$=sDirSave$+starFileName[Temp_j]$+"-1.fits"
                FileExists  File$  TargetAlreadyAcquired
                Now Date
                Datetostr Date Date$
                print "[" Date$ "] Target " File$ "Valid?=" TargetAlreadyAcquired

                if TargetAlreadyAcquired=FALSE then
                    print "[" Date$ "] Target confirmed : " starFileName[Temp_j]$
                    NumeroObject=NumeroObject+1
                    Now Date
                    Datetostr Date Date$
                    print "[" Date$ "] Next target (#" NumeroObject ") : " starFileName[Temp_j]$ " RA=" starRA[Temp_j] " DEC=" starDec[Temp_j] " Vmag=" starVMag[Temp_j] " Guiding Exp Time=" starGuideExposureSec[Temp_j] " BeSS=" starWeightBeSS[Temp_j] " MyPrio=" starWeightOTH[Temp_j] " Distance=" starWeightDistance[Temp_j]
                    Object$=starFileName[Temp_j]$
                    objet$=starname[Temp_j]$
                    myObjectName$=myobjname[Temp_j]$
                    GExpTime=starGuideExposureSec[Temp_j]
                    ExpSec=starExpTimeSec[Temp_j]
                    NbExposure=starNbExposure[Temp_j]

                    GoSub GoToTargetAndAcquisition:
                   
                    File$=sDirSave$+starFileName[Temp_j]$+"-1.fits"
                    FileExists  File$  TargetAlreadyAcquired

                    if TargetAlreadyAcquired=FALSE then
                        Now Date
                        Datetostr Date Date$
                        print "[" Date$ "] Waiting 5min for a new target to come nearby..."
                        stoptelescope
                        DelayBlock 300000
                    endif

               
                    GoTo LoopAcquisitionOfTargets:
                endif
            endif
        next Temp_i

        Now Date
    Datetostr Date Date$
    print "[" Date$ "] No target found, waiting for 5min..."       
    DelayBlock 300000
    GoTo LoopAcquisitionOfTargets:

endif

EndOfSession:
// END OF SESSION
print "-----------------------------------------------------------"
EquipmentClosed=0
// Synch on bet And first
GoSub IsSunStillBelow:
if SunStillBelow=1 then
// Add synchronisation on a star there is needed (not really needed anymore)
else
    GoSub endnight:
    GoTo EndOfMainSequence:
endif
// Synch on eta Psc then
GoSub IsSunStillBelow:
if SunStillBelow=1 then
// Add synchronisation on a star there is needed (not really needed anymore)
else
    GoSub endnight:
    GoTo EndOfMainSequence:
endif


FinishScriptHere:
GoSub endnight:

EndOfMainSequence:


// Et message de fin...
Now Date
Datetostr Date Date$
print "[" Date$ "] That's all folks..."

sOutput$=" "
Print sOutput$

sOutput$="DDD     OOO  N    N EEEEE"
Print sOutput$
sOutput$="D  D   O   O N N  N E    "
Print sOutput$
sOutput$="D   D  O   O N  N N EEE  "
Print sOutput$
sOutput$="D  D   O   O N   NN E    "
Print sOutput$
sOutput$="DDD     OOO  N    N EEEEE"
Print sOutput$

sOutput$=" "
Print sOutput$


END



/////////////////////////////////////////////////////////////////////////////////
//
// Goto a target, center object, run autoguiding and acquire spectra
//
/////////////////////////////////////////////////////////////////////////////////

GoToTargetAndAcquisition:

    print "-----------------------------------------------------------"

    REM Coordonnées équatoriales de l'objet en radians
    GETOBJECTCOORD objet$ alpha delta

    if alpha=-100
      Now Date
      Datetostr Date Date$
      print "[" Date$ "] Object " objet$ " is not recognized by PRISM !"
      return
    endif

    str alpha alphaRad$
    str delta deltaRad$
    RAD_TO_RA  alpha alpha$
    RAD_TO_DEC delta delta$

    Now Date
    Datetostr Date Date$
    PRINT "[" Date$ "] " Object$ " (" objet$ ") is at coordinates :"
    PRINT "[" Date$ "] RA  : " alpha$ " (" alphaRad$ " radians)"
    PRINT "[" Date$ "] DEC : " delta$ " (" deltaRad$ " radians)"

    //Longitude du lieu = celle du site par défaut
    GETSTDRLONGITUDE Longitude
    // Latitude du lieu
    GETSTDRLATITUDE Latitude
    // Loop to wait for the target to reach proper altitude in the sky
    LoopWaitHauteur:
    // Date du moment :
    NOW Date
    // Hauteur de l'objet en radian :
    GETHEIGHT alpha delta Date Longitude Latitude Hauteur
    // Hauteur en degrés
    Hauteur=Hauteur*TODEG

    if Hauteur<HauteurMin then
       stoptelescope
       Now Date
       Datetostr Date Date$
       print "[" Date$ "] Target too low, elevation at " Hauteur " target: " HauteurMin ")"
       DelayBlock 300000
       Goto LoopWaitHauteur:
    endif


    // Look for telescope position at the end of acquisition to check if not past meridian+limit / give 50% margin to allow half exposure...
    // TSL pour calculer angle horaire
    SIDERALTIME Date Longitude TSL
    // Angle horaire objet en radian :
    COMPUTEANGLEHOR TSL alpha AngleHor
    //Angle horaire en heures décimales:
    AngleHor=AngleHor*12/PI
    AngleHorEndOfExposure=AngleHor+((ExpSec*NbExposure)/3600.0)/2.0

    AngleHorLimit=0.0
    // si DEC<45°: 10min supplémentaires
    if delta<(45.0/180.*3.1415) then
        AngleHorLimit=0.0/60.0
    endif
    // si DEC<30°: 20min supplémentaires -> 15min
    if delta<(30.0/180.*3.1415) then
        AngleHorLimit=0.0/60.0
    endif
    // si DEC<25°: 1h10 supplémentaires -> diminué à 20min par sécurité
    if delta<(25.0/180.*3.1415) then
        AngleHorLimit=0.0/60.0
    endif
    // si DEC<6°: 1h45 supplémentaires -> diminué à 30min par sécurité?
    if delta<(6.0/180.*3.1415) then
        AngleHorLimit=0.0/60.0
    endif

    if AngleHorEndOfExposure>AngleHorLimit
       Now Date
       Datetostr Date Date$
       print "[" Date$ "] Target at mid sequence will be at hour angle: " AngleHorEndOfExposure " so target skipped"
       return
    endif


    // Pointage ou non ?
    If AngleHor<AngleHorMin then
        If Hauteur>HauteurMin then
            str Hauteur Hauteur$
            Now Date
            Datetostr Date Date$
            print "[" Date$ "] GoTo Target at Elevation : " Hauteur$ "°"
            WaitForDome=1
            alphaplus=alpha+0.003
            deltaplus=delta+0.003
            if alphaplus>TwoPI then
                alphaplus=alphaplus-2*PI
            endif
            MoveTelescope alphaplus deltaplus
            WaitForEndMoveTelescope
            DelayBlock WaitForDomeTime
            alphaplus=alphaplus-0.003
            deltaplus=deltaplus-0.003
            if alphaplus<0 then
                alphaplus=alphaplus+2*PI
            endif
            MoveTelescope alphaplus deltaplus
            WaitForEndMoveTelescope
            DelayBlock 10000
        Else
            Now Date
            Datetostr Date Date$
            print "[" Date$ "] Target too low"
            return
        EndIf
    Else
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Target too close to meridian"
        return
    EndIf

    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Telescope at target position now"


    // Wait for the dome
    //Now Date
    //Datetostr Date Date$
    //print "[" Date$ "] Waiting for the dome"
    //DelayBlock WaitForDomeTime
    //Now Date
    //Datetostr Date Date$
    //print "[" Date$ "] Dome should be at telescope position now"


    GoSub CalculateNightDate:


    // First do a long exposure and an astrometry to resynch telescope
    if AllowAstrometry=TRUE then
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Acquiring a long exposure and trying an astrometry first"
        StartExposure_EX 1 GExpTimeAstrometryChamp
        WaitForEndExposure_EX 1
        GetLastImageExposure_EX 1 ImgChampToCenter

        sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+"_astrometry.fits"
        SAVEFIT ImgChampToCenter sFullPath$
        sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+"_astrometry.jpg"
        SAVEJPG ImgChampToCenter sFullPath$

        BinX=2
        BinY=BinX
        BINNINGREDUCE  ImgChampToCenter  BinX  BinY

        FIND_ALLSKY_POSITION ImgChampToCenter MaxStarImg MaxStarCat FieldAllSky CatalogAst$ Valid
       
        if Valid=TRUE then
            GetAlpha ImgChampToCenter AD
            GetDelta ImgChampToCenter DC
            // STR DC DC$
            // STR AD AD$
            RAD_TO_RA  AD AD$
            RAD_TO_DEC DC DC$
            Now Date
            Datetostr Date Date$
            print "[" Date$ "] Astrometry OK, resynchronizing telescope at RA=" AD$ ", DEC=" DC$

            // Check if I was close enough to the target and GoTo again if necessary
            DeltaADPixel=3600*180*(alpha-AD)/(PI*EchelleXFactAstro)
            if DeltaADPixel<0 then
                DeltaADPixel=-DeltaADPixel
            endif
            DeltaDCPixel=3600*180*(delta-DC)/(PI*EchelleYFactAstro)
            if DeltaDCPixel<0 then
                DeltaDCPixel=-DeltaDCPixel
            endif
           
            AmICloseEnough=FALSE
            MarginMax=(GuideXMax_2-ZoneRecherche)
           
            if DeltaADPixel<MarginMax then
                if DeltaDCPixel<MarginMax then
                    AmICloseEnough=TRUE
                endif
            endif

            STR DeltaADPixel DeltaADPixel$
            STR DeltaDCPixel DeltaDCPixel$
           
            if AmICloseEnough=TRUE then
                Now Date
                Datetostr Date Date$
                print "[" Date$ "] Telescope close enough to target (dX=" DeltaADPixel$ ", dY=" DeltaDCPixel$ ") so skipping a new GoTo now"
            else
                Now Date
                Datetostr Date Date$
                print "[" Date$ "] Telescope too far from target (dX=" DeltaADPixel$ ", dY=" DeltaDCPixel$ ") / GoTo target again"
                alphaplus=alpha+0.003
                deltaplus=delta+0.003
                if alphaplus>TwoPI then
                    alphaplus=alphaplus-2*PI
                endif
                MoveTelescope alphaplus deltaplus
                WaitForEndMoveTelescope
                DelayBlock 10000
                alphaplus=alphaplus-0.003
                deltaplus=deltaplus-0.003
                if alphaplus<0 then
                    alphaplus=alphaplus+2*PI
                endif
                MoveTelescope alphaplus deltaplus
                WaitForEndMoveTelescope
                DelayBlock 10000
            endif
        else
            Now Date
            Datetostr Date Date$
            print "[" Date$ "] Astrometry didn't work"
        endif

        CLOSE ImgChampToCenter

    endif

   
//    if AmICloseEnough=TRUE then
//        Now Date
//        Datetostr Date Date$
//        print "[" Date$ "] and no need to search for brigthest star"
//    else
    // Centering the brightest star on the consign (fiber hole) position
    GExpTimeMilSec=GExpTime*1000
    GExpTimeChamp=GExpTimeMilSec*5
    StartExposure_EX 1 GExpTimeChamp
    WaitForEndExposure_EX 1
    GetLastImageExposure_EX 1 ImgChampToCenter
    sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+"_tocenter.fits"
    SAVEFIT ImgChampToCenter sFullPath$
    sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+"_tocenter.jpg"
    SAVEJPG ImgChampToCenter sFullPath$

    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Looking for beightest star in the field"

    BinX=4
    BinY=BinX
    BINNINGREDUCE  ImgChampToCenter  BinX  BinY

    // Alternative to limit number of stars to look for: BRIGHTEST_STAR2 Img SeuilMin SeuilMax OmC PSFMin DemiLargeur SearchField MaxPoints Xcentro Ycentro
    BRIGHTEST_STAR ImgChampToCenter MinDynamiqueAutoguidage MaxDynamique MaxOmC PSFMin DemLargFenCentro ZoneRecherche XGuideCentro YGuideCentro
   
    if YGuideCentro<0 then
        XGuideCentro=-1
    endif
    if XGuideCentro<0 then
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Star not found... Skipping target for now"
        CLOSE ImgChampToCenter
        return
    endif
    str XGuideCentro XStar$
    str YGuideCentro YStar$
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Star found at position (taking into account 'Facteur') " XStar$ ", " YStar$
    str GuidePosXFact GuidePosX$
    str GuidePosYFact GuidePosY$

    // margin (GuideXMax_2-ZoneRecherche)
    MarginX=(GuidePosXFact-XGuideCentro)
    MarginY=(GuidePosYFact-YGuideCentro)
    if MarginX<0 then
        MarginX=0-MarginX
    endif
    if MarginY<0 then
        MarginY=0-MarginY
    endif
    if MarginX<MarginY then
        Margin=MarginY/Facteur
    else
        Margin=MarginX/Facteur
    endif
    MarginMax=(GuideXMax_2-ZoneRecherche)

    if Margin<MarginMax then
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Taget close to fiber, no need to center it and go to autoguiding directly"
    else
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Centering at Fiber position at (incl. Facteur) " GuidePosX$ ", " GuidePosY$
        //    OFFSET_TELESCOPE ImgChampToCenter XGuideCentro YGuideCentro GuidePosX GuidePosYDecale
       
        GET_TELESCOPE_POSITION RA2000 DEC2000 Haut Azi AHor
        // str RA2000 RA$
        // str DEC2000 DEC$
        RAD_TO_RA  RA2000 RA$
        RAD_TO_DEC DEC2000 DEC$
        print "[" Date$ "] RA2000=" RA$ ", DEC2000=" DEC$

        // For some reason I have to substract 14.3 arcsec in my RA position to be OK... ASCOM or Gemini.Net problem ???
        AlphaNew=alphaplus-(GuidePosXFact-XGuideCentro)*EchelleXFact/3600*3.1415/180
        DeltaNew=deltaplus-(GuidePosYFact-YGuideCentro)*EchelleYFact/3600*3.1415/180
        // str alphaplus RA$
        // str deltaplus DEC$
        RAD_TO_RA  alphaplus RA$
        RAD_TO_DEC deltaplus DEC$
        print "[" Date$ "] AlphaPlus=" RA$ ", DecPlus=" DEC$
        str AlphaNew RA$
        str DeltaNew DEC$
        RAD_TO_RA  AlphaNew RA$
        RAD_TO_DEC DeltaNew DEC$
        print "[" Date$ "] AlphaNew=" RA$ ", Dec.New=" DEC$

        print "[" Date$ "] Shifting Telescope (two steps approach)"

        // GoTo nearby (to work around a bug in ASCOM / POTH / Gemini.Net)
        AlphaNew=AlphaNew+0.003
        DeltaNew=DeltaNew+0.003
        if AlphaNew>TwoPI then
            AlphaNew=AlphaNew-2*PI
        endif
        MoveTelescope AlphaNew DeltaNew
        WAITFORENDMOVETELESCOPE
        DelayBlock 2000

        // Then GoTo the right position (should be very close to fiber now...
        AlphaNew=AlphaNew-0.003
        DeltaNew=DeltaNew-0.003
        if AlphaNew<0 then
            AlphaNew=AlphaNew+2*PI
        endif
        MoveTelescope AlphaNew DeltaNew

        WAITFORENDMOVETELESCOPE
        DelayBlock 2000

    endif
   
    CLOSE ImgChampToCenter

    if AskForManualAutoGuiding=TRUE then
        Input "Wait for Dome, Center target and then press ENTER" Dummy$
    endif

    GExpTimeChamp=GExpTimeMilSec*40
   
    if GExpTimeChamp>60000 then
        GExpTimeChamp=60000
    endif
   
    StartExposure_EX 1 GExpTimeChamp
    WaitForEndExposure_EX 1
    GetLastImageExposure_EX 1 ImgChamp


    // Sauvegarde de l'image de guidage surexposée (FITS et JPG)
    sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+".fits"
    SAVEFIT ImgChamp sFullPath$
    sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+".jpg"
    SAVEJPG ImgChamp sFullPath$
    CLOSE ImgChamp

    if AskForManualAutoGuiding=TRUE then
        Input "Start autoguiding manually - then press ENTER" Dummy$
    else

        DelayBlock 5000
           

        // Run autoguiding
        TRUE=1
        FALSE=0

        NumCam=1
        CCDNum=1
    //    GExpTime=0.5
        DelayACQSec=GuidingDelayACQSec
        WindowSize=GuideXMax_2
        CentroSize=GuidingCentroSize
        StarThresADU=GuidingStarThresADU
        AgressRA=0.7
        AgressDEC=0.7
        RaMin=3.0
        RaMax=GuideXMax_2
        DecMin=3.0
        DecMax=GuideXMax_2
        Backlash=0
        CurrentDEC=FALSE
        AlarmEnabled=FALSE
        DeltaMoveFashion=FALSE
    //    GuidePosX=291.0
    //    GuidePosY=213.0
        SaveImagettes=FALSE
        DirSaveImg$="c:\ccd"
        AllFrame=TRUE
        WindowAllFrame=400
        WaitForScript=60

        GExpTimeBis=GExpTime*GuidingExpFactor

        str GExpTimeBis GExpTimeBis$
       
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Autoguidage ON (ExpTime: " GExpTimeBis "ms)"
        STARTGUIDECONSIGNE NumCam CCDNum GExpTimeBis DelayACQSec WindowSize CentroSize StarThresADU AgressRA AgressDEC RaMin RaMax DecMin DecMax Backlash CurrentDEC AlarmEnabled DeltaMoveFashion GuidePosX GuidePosY SaveImagettes DirSaveImg$ AllFrame WindowAllFrame Valid message$
   
        DelayBlock 5000
    endif

    //str Valid Valid$
    //Now Date
    //Datetostr Date Date$
    //print "[" Date$ "] Valid: " Valid$ " / Status: " message$

    /////////////////////
    // Acquiring Target
    /////////////////////
    ExpTime=ExpSec*1000


    REM StatWindow Img  X1  Y1  X2  Y2  Mean  Quadratic_mean  Stddev  Max  Min  Flux  Median
    HaX1=864
    HaY1=1710
    HaX2=984
    HaY2=1722
    ContX1=1543
    ContY1=1640
    ContX2=1588
    ContY2=1189

    WinPosX=500
    WinPosY=100
    WinSizeX=1000
    WinSizeY=1000



    str ExpSec ExpSec$
    str NbExposure NbExposure$

    sOutput$="Starting sequence for Target: "+Object$+" ("+NbExposure$+" x "+ExpSec$+" seconds)"
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] " sOutput$
    sOutput$="Target filename: "+Object$
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] " sOutput$

    GetStdrLongitude Longitude
    GetStdrLatitude Latitude
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Longitude = " Longitude*TODEG " Latitude = " Latitude*TODEG
    Now Date
    GETRADECSUN  Date  AlphaS  DeltaS  sunelevation
    Datetostr Date Date$
    RAD_TO_DEC sunelevation ElevationS$
    GET_TELESCOPE_POSITION Alpha2000 Delta2000 Hauteur Azimuth AngleHor
    // TSL pour calculer angle horaire
    SIDERALTIME Date Longitude TSL
    // Angle horaire objet en radian :
    COMPUTEANGLEHOR TSL alpha AngleHor
    Hauteur=Hauteur*TODEG
    AngleHor=AngleHor*TODEG/15.0
    round Hauteur Hauteur
    AngleHor=AngleHor*10.0
    round AngleHor AngleHor
    AngleHor=AngleHor/10.0
    str Hauteur Hauteur$
    str AngleHor AngleHor$
    print "[" Date$ "] Sun at " ElevationS$ "°, Telescope at " Hauteur$ "° & Hour Angle: " AngleHor "h"

    MaxHaAvg=0
    MaxContAvg=0
    NbMeasures=0

    For i=1 NbExposure
      // Ensure proper Dome tracking - just to make sure...
      DOME_SET_CONTROL 1 1

      GoSub CanIContontinueToObserve:

      if ContinueObservations=0 then
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Sun too high, stopping observations"
        GoTo EndOfGoToTargetAndAcquisition:
      endif
     
      StartExposure_EX 2 ExpTime
      WaitForEndExposure_EX 2
      GetLastImageExposure_EX 2 img

      STR i i$
      sFullPath$=sDirSave$+Object$+"-"+i$+".fits"
      SAVEFIT img sFullPath$


      StatWindow Img  HaX1  HaY1  HaX2  HaY2  Mean  Quadratic_mean  Stddev  Max  Min  Flux  Median
      MaxHa=Max-Min
      MaxHaAvg=MaxHaAvg+MaxHa
      NbMeasures=NbMeasures+1
      str MaxHa MaxHa$
      StatWindow Img  ContX1  ContY1  ContX2  ContY2  Mean  Quadratic_mean  Stddev  Max  Min  Flux  Median
      MaxCont=Max-Min
      MaxContAvg=MaxContAvg+MaxCont
      str MaxCont MaxCont$
      sOutput$=">>> "+i$+" <<< : Max. Ha="+MaxHa$+" / Continuum="+MaxCont$
      Now Date
      Datetostr Date Date$
      print "[" Date$ "] " sOutput$
      GetStdrLongitude Longitude
      GetStdrLatitude Latitude
      Now Date
      GETRADECSUN  Date  AlphaS  DeltaS  sunelevation
      Datetostr Date Date$
      RAD_TO_DEC sunelevation ElevationS$
      GET_TELESCOPE_POSITION Alpha2000 Delta2000 Hauteur Azimuth AngleHor
      // TSL pour calculer angle horaire
      SIDERALTIME Date Longitude TSL
      // Angle horaire objet en radian :
      COMPUTEANGLEHOR TSL alpha AngleHor
      //Angle horaire en heures décimales:
      //AngleHor=AngleHor*12/PI
      Hauteur=Hauteur*TODEG
      AngleHor=AngleHor*TODEG/15.0
      round Hauteur Hauteur
      AngleHor=AngleHor*10.0
      round AngleHor AngleHor
      AngleHor=AngleHor/10.0
      str Hauteur Hauteur$
      str AngleHor AngleHor$
      print "[" Date$ "] Sun at " ElevationS$ "°, Telescope at " Hauteur$ "° & Hour Angle: " AngleHor "h"

      SetWindowPos img WinPosX WinPosY
      SizeWindowX img WinSizeX
      SizeWindowY img WinSizeY

      Close img
      DelayBlock 3000

    Next i

    EndOfGoToTargetAndAcquisition:

    if NbMeasures>0 then
          MaxHaAvg=MaxHaAvg/NbMeasures
          round MaxHaAvg MaxHaAvg
          MaxContAvg=MaxContAvg/NbMeasures 
          round MaxContAvg MaxContAvg
          str MaxHaAvg MaxHaAvg$
          str MaxContAvg MaxContAvg$
          Now Date
          Datetostr Date Date$
          print "[" Date$ "] STATISTICS: Halpha at " MaxHaAvg$ ", continuum at: " MaxContAvg$
          str NbMeasures NbMeasures$
         
          // save stats
          Open_FileTxt_For_Append  fichier StatsLog$
          if MaxHaAvg>MaxContAvg then
            StatsMax=MaxHaAvg/1000.0
          else
            StatsMax=MaxContAvg/1000.0
          endif
          str StatsMax StatsMax$
          texte$=DateStats$+";"+myObjectName$+";"+ExpSec$+";"+NbMeasures$+";"+Hauteur$+";"+StatsMax$
          WRITEFILETXT  fichier  texte$
          CLOSEFILETXT  fichier

          // save just BeSS object name (usually HD  #) & date (goal is to avoid redoing them the following nights depending on BeSS required period... work in progress)
          Open_FileTxt_For_Append  fichier ObjectLog$
          texte$=Objet$+";"+Date$
          WRITEFILETXT  fichier  texte$
          CLOSEFILETXT  fichier
     endif

    if AskForManualAutoGuiding=TRUE then
        Now Date
        Datetostr Date Date$
        print "[" Date$ "]                        ===="
        print "[" Date$ "] =============================="
        print "[" Date$ "]          ========================="
        print "[" Date$ "] =============================="
        print "[" Date$ "]                        ===="
        Input "Please STOP autoguiding manually - then press ENTER" Dummy$
    else
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Stopping autoguiding"
        StopGuide_Ex 1 1
    endif
   
    GExpTimeChamp=GExpTimeMilSec*40
   
    if GExpTimeChamp>60000 then
        GExpTimeChamp=60000
    endif
   
    StartExposure_EX 1 GExpTimeChamp
    WaitForEndExposure_EX 1
    GetLastImageExposure_EX 1 ImgChamp


    // Sauvegarde de l'image de guidage surexposée après séquence(FITS et JPG)
    sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+"_after.fits"
    SAVEFIT ImgChamp sFullPath$
    sFullPath$=sDirSave$+"ZWO_ASI174MM_"+Object$+"_after.jpg"
    SAVEJPG ImgChamp sFullPath$
    CLOSE ImgChamp

    // Synchronise télescope sur la cible pointée (car ça a bougé pendant l'autoguidage)
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Resynch telescope on position for " Object$ " (" objet$ ")"
    CALIBRATE_TELESCOPE alpha delta

    DelayBlock 15000
return



/////////////////////////////////////////////////////////////////////////////////
//
// Start_and_Calib - Routine to begin the night: connecting equipment, spectral calibration, opening dome...
//
/////////////////////////////////////////////////////////////////////////////////

Start_and_Calib:

    // Switch ON Gembird USB & LAN multiplug
    if CheckIfPowerManagerIsOK=1 then
        Input "Please check Power Manager is ON, OK and connect to USB socket - then press ENTER" Dummy$
    else
        ExecExternal "C:\Program Files\Power Manager\pm.exe" ""
        delayBlock 3000
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Power Manager started"
    endif

    REM Switch ON the power for the mount, dome & focuser
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Switching mount, dome & robofocus ON"
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-on -Device3 -Mount"
    delayBlock 1000
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-on -Device3 -DomeTrackerd"
    delayBlock 1000
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-on -Device3 -RoboFocus"
    if ConnectTelescopeManually=1 then
        Input "Please connect Telescope/Dome/Focuser in PRISM... and press ENTER" Dummy$
    else
        delayBlock 15000
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Connecting to Telescope/Dome/Focuser"
        CONNECT_OBSERVATORY Valid
        delayBlock 30000
    endif
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Stopping the sidereal tracking"
    stoptelescope
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Set dome moving on telescope tracking & GoTo"
    DOME_SET_CONTROL 1 1
    delayBlock 3000


    REM *** calculating night's directory

    GoSub CalculateNightDate:
    createdir sDirSave$
    createdir sDirSave$+"CALIB"
    ExecExternal "C:\Users\ObsBE\Documents\Acquisitions\CALIB\CopyDirs.bat" sDirSave$+"CALIB"
    ExecExternal "C:\Users\ObsBE\Documents\Acquisitions\CALIB\CopyZip.bat" sDirSave$+"Resultats"   
    createdir sDirSave$+"Poubelle"
    createdir sDirSave$+"Raw"
    createdir sDirSave$+"Resultats"
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Tonight directory is: "+sDirSave$




    REM *** Waiting for the Sun to be below "elevsunstartinitnight" to start initialising CCD
    GetStdrLongitude Longitude
    GetStdrLatitude Latitude
    REM print "Longitude = " Longitude*TODEG " Latitude = " Latitude*TODEG

    elevsunstartinitnight=elevsunstartinitnight_Deg/TODEG

    beginnighttime:
    Now Date
    Datetostr Date Date$
    GETRADECSUN  Date  AlphaS  DeltaS  sunelevation
    RAD_TO_DEC sunelevation ElevationS$
    if sunelevation>0
       position$="above"
    else
       position$="below"
    endif
    print "[" Date$ "] Sun at " ElevationS$ position$ " horizon (Tgt: " elevsunstartinitnight_Deg "°)"
    if sunelevation>elevsunstartinitnight
       delayBlock 60000
       goto beginnighttime:
    endif
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] The sun is now " ElevationS$ " degrees below horizon, starting up camera and mount"


    REM Switch ON Gembird LAN multiplug: calibration unit & Atik460 CCD camera
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-on -GemBirdLAN -Atik460"
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Atik 460 camera power ON now"

    delayBlock 10000
      

    REM *** Initialisations CCDs
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Connect/Initialise guiding (#1) & acquisition (#2) cameras; cooling the main one"
    GoSub init_camera:


    elevsunstartbegnight=elevsunstartbegnight_Deg/TODEG

    REM *** Waiting for the sun to be below "elevsunstartbegnight", then start telescope & open dome
    waittillstarttime:
    Now Date
    GETRADECSUN  Date  AlphaS  DeltaS  sunelevation
    Datetostr Date Date$
    RAD_TO_DEC sunelevation ElevationS$
    if sunelevation>0
       position$="above"
    else
       position$="below"
    endif
    print "[" Date$ "] Sun at " ElevationS$ position$ " horizon (Tgt: " elevsunstartbegnight_Deg "°)"
    if sunelevation>elevsunstartbegnight
       delayBlock 60000
       goto waittillstarttime:
    endif
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] The sun is now " ElevationS$ " degrees below horizon, starting the observations"


    REM echelle calibration
    REM Switch ON Gembird LAN multiplug: calibration unit
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Switch calibration unit ON & start spectral calibration"
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-on -GemBirdLAN -Calib"

    delayBlock 3000
    if SkipCalibration=0
        GoSub AcquireCalibration:
    endif

    REM Switch OFF Gembird LAN multiplug: calibration unit
    delayBlock 3000
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Switch calibration unit OFF"
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-off -GemBirdLAN -Calib"


    REM *** Waiting for the Sun to be below "elevsunstartobservations" to start observations
    GetStdrLongitude Longitude
    GetStdrLatitude Latitude
    REM print "Longitude = " Longitude*TODEG " Latitude = " Latitude*TODEG

    elevsunstartobservations=elevsunstartobservations_Deg/TODEG

    beginobservationtime:
    Now Date
    GETRADECSUN  Date  AlphaS  DeltaS  sunelevation
    Datetostr Date Date$
    RAD_TO_DEC sunelevation ElevationS$
    if sunelevation>0
       position$="above"
    else
       position$="below"
    endif
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Sun at " ElevationS$ position$ " horizon (Tgt: " elevsunstartobservations_Deg "°)"
    if sunelevation>elevsunstartobservations
       delayBlock 60000
       goto beginobservationtime:
    endif
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] The sun is now " ElevationS$ " degrees below horizon, ready to start observations"


    // Open DOME and start observations !


    if OpenDomeManually=1 then
        Input "Please open Dome when ready - then press ENTER" Dummy$
    else
        Open_Dome
        DelayBlock 30000
    endif
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Dome is now open"

return




/////////////////////////////////////////////////////////////////////////////////
//
// Subroutine to initialize the camera, contains informations and settings of the camera
//
/////////////////////////////////////////////////////////////////////////////////

init_camera:
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Connecting the Zwo ASI178MC guiding camera (1)"
    cameraerror$=""
    INIT_CCD_CAMERA_EX  GuidingCamNumber Valid  cameraerror$
    if Valid=2 then
       nbinning=1
       SetBinningX_Ex GuidingCamNumber nBinning
       SetBinningY_Ex GuidingCamNumber nBinning
    else
       Now Date
       Datetostr Date Date$
       print "[" Date$ "] ERREUR initialisation camera 1: Atik Titan"
       print cameraerror$
       EXIT
    endif  

    REM We start the camera
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Connecting the Atik 460ex camera (2)"
    Detector_number=2
    CameraChannel=1
    cameraerror$=""
    INIT_CCD_CAMERA_EX  AcqCamNumber Valid  cameraerror$
    if Valid=2 then
       nbinning=1
       SetBinningX_Ex AcqCamNumber nBinning
       SetBinningY_Ex AcqCamNumber nBinning
       for i=1 to minutestogodowntotemp
          GetCCDTemperature_Ex  AcqCamNumber CameraChannel Starttemperature
          deltaT=Detectortemperature-Starttemperature
          deltaTperminute=deltaT/minutestogodowntotemp
          Now Date
          Datetostr Date Date$
          print "[" Date$ "] Going from " Starttemperature " to " Detectortemperature " we need to cool " deltaTperminute " degrees per minute"
          Currenttemperature=Starttemperature+(deltaTperminute*i)
          round Currenttemperature Currenttemperature
          if Currenttemperature<Detectortemperature+0.2 then
             goto endcooling1:
          else
          SetCCDTemperature_Ex AcqCamNumber CameraChannel Currenttemperature
          Now Date
          Datetostr Date Date$
          print "[" Date$ "] " i " minute, CCD going down to " Currenttemperature " degrees"
          delayBlock 60000
          endif
       next i
    else
       REM The camera didn't initialize correctly
       Now Date
       Datetostr Date Date$
       print "[" Date$ "] ERREUR initialisation camera 2: Atik 460ex"
       print cameraerror$
       EXIT
    endif  

    endcooling1:
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] END COOLING"
    SetCCDTemperature_Ex AcqCamNumber CameraChannel Detectortemperature  
return



/////////////////////////////////////////////////////////////////////////////////
//
// Initializing the telescope / NOT USED...
//
/////////////////////////////////////////////////////////////////////////////////

init_telescope:
    print "Connecting to the telescope"
    OPEN_TELESCOPE_DEVICES 0 0
    print "Connected"
    print "stopping the sidereal tracking..."
    stoptelescope
return



/////////////////////////////////////////////////////////////////////////////////
//
// End of night, closing telescope, camera, etc...
//
/////////////////////////////////////////////////////////////////////////////////

endnight:
    REM We have to see how to bring the camera back to ambient temperature before closing it.
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Observing is finished, so closing the telescope..."



    REM Closing the telescope
    //CLOSE_TELESCOPE_DEVICES
    close_dome
    delayBlock 20000
    stoptelescope
    delayBlock 10000

    // A ajouter: prévoir le cas de la calibration en fin de nuit si météo mauvaise en début de nuit...
    //GoSub AcquireCalibration:

    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Setting main camera temperature to positive (10°C) & wait 2 minutes"
    Currenttemperature=20
    CameraChannel=1
    SetCCDTemperature_Ex AcqCamNumber CameraChannel Currenttemperature
    delayBlock 120000

    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Closing cameras connexion"
    CLOSE_CCD_CAMERA_EX 1
    delayBlock 2000   
    CLOSE_CCD_CAMERA_EX 2

    close_dome

    delayBlock 20000

    CLOSE_TELESCOPE_DEVICES
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Telescope tracking stopped & dome closed, equipment closed"
   
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Switching OFF mount, dome, robofocus and CCD cameras"

    REM Switch OFF the power for the mount, dome & focuser
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-off -Device3 -Mount"
    delayBlock 2000   
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-off -Device3 -DomeTracker"
    delayBlock 2000   
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-off -Device3 -RoboFocus"
    delayBlock 2000

    REM Switch OFF Gembird LAN multiplug: calibration unit & Atik460 CCD camera
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-off -GemBirdLAN -Calib"
    delayBlock 2000   
    ExecExternal "C:\Program Files\Power Manager\pm.exe" "-off -GemBirdLAN -Atik460"
    delayBlock 2000

    Now Date
    Datetostr Date Date$
    print "[" Date$ "] End of night sequence done"

return


/////////////////////////////////////////////////////////////////////////////////
//
// Acquire calibration for the echelle spectrograph
//
/////////////////////////////////////////////////////////////////////////////////

AcquireCalibration:
    REM Penser à enlever la sauvegarde automatique dans PRISM avant de lancer le script!

    Object$="ref"

    PoseThAr=60000
    PoseTung=2800
    PoseLEDs=2800
    ON=1
    OFF=0
    Port1=1
    Port2=2
    Port3=3
    Port4=4


    Switchdesired=1
    // Recupere l'etat des swiches d'un coup dans une table
    GETSWITCH Switchdesired nbSwitches ArrayName ArrayState

    sOutput$="Dir: "+sDirSave$
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] " sOutput$
    sOutput$="Object: "+Object$
    print "[" Date$ "] " sOutput$


    REM =================
    REM Miroir + Tungsten
    REM =================
    SETSWITCH Port1 ON
    DelayBlock 1000
    SETSWITCH Port4 ON
    DelayBlock 1000

    For i=1 33
      STR i i$
      StartExposure_EX AcqCamNumber PoseTung
      sFullPath$=sDirSave$+Object$+"_tung-"+i$+".fits"
      sOutput$="Tungsten: "+Object$+"_tung-"+i$+".fits"
      Now Date
      Datetostr Date Date$
      print "[" Date$ "] " sOutput$
      WaitForEndExposure_EX AcqCamNumber
      GetLastImageExposure_EX AcqCamNumber img
      SAVEFIT img sFullPath$
      Close img
    Next i


    REM =================
    REM LEDs + Tungsten
    REM =================
    SETSWITCH Port2 ON
    DelayBlock 1000

    For i=1 3
      STR i i$
      StartExposure_EX AcqCamNumber PoseLEDs
      sFullPath$=sDirSave$+Object$+"_led-"+i$+".fits"
      sOutput$="Flat: "+Object$+"_led-"+i$+".fits"
      Now Date
      Datetostr Date Date$
      print "[" Date$ "] " sOutput$
      WaitForEndExposure_EX AcqCamNumber
      GetLastImageExposure_EX AcqCamNumber img
      SAVEFIT img sFullPath$
      Close img
    Next i

    DelayBlock 2000

    SETSWITCH Port2 OFF
    DelayBlock 2000

    SETSWITCH Port4 OFF
    DelayBlock 2000


    REM =================
    REM ThAr
    REM =================
    SETSWITCH Port3 ON
    DelayBlock 3000

    For i=1 3
      STR i i$
      StartExposure_EX AcqCamNumber PoseThAr
      sFullPath$=sDirSave$+Object$+"_thor-"+i$+".fits"
      sOutput$="ThAr: "+Object$+"_thor-"+i$+".fits"
      Now Date
      Datetostr Date Date$
      print "[" Date$ "] " sOutput$
      WaitForEndExposure_EX AcqCamNumber
      DelayBlock 1000
      GetLastImageExposure_EX AcqCamNumber img
      DelayBlock 1000
      SAVEFIT img sFullPath$
      Close img
      DelayBlock 1000
    Next i

    DelayBlock 3000

    SETSWITCH Port3 OFF
    DelayBlock 1000

    SETSWITCH Port1 OFF
    DelayBlock 1000

    REM sOutput$="That's all folks"
    REM Print sOutput$

return



/////////////////////////////////////////////////////////////////////////////////
//
// Check if I can continue to observe another 20min based on Sun position & telescope Vs meridian
//
/////////////////////////////////////////////////////////////////////////////////

CanIContontinueToObserve:
    NOW Date
    GET_TELESCOPE_POSITION RA2000 DEC2000 Haut Azi AHor
    GETSTDRLONGITUDE Longitude
    GETSTDRLATITUDE Latitude
    GETHEIGHT RA2000 DEC2000 Date Longitude Latitude Hauteur
    // Hauteur en degrés
    Hauteur=Hauteur*TODEG

    if Hauteur<HauteurMin then
       Now Date
       Datetostr Date Date$
       print "[" Date$ "] Target too low"
       ContinueObservations=0
       return
    endif

    DateEndOfObs=Date+ExpSec/(3600.0*24.0)
    // TSL pour calculer angle horaire
    SIDERALTIME DateEndOfObs Longitude TSL
    // Angle horaire objet en radian :
    COMPUTEANGLEHOR TSL RA2000 AngleHor
    //Angle horaire en heures décimales:
    AngleHor=AngleHor*12/PI

    AngleHorLimit=0.0
    // si DEC<45°: 10min supplémentaires
    if DEC2000<0.75 then
        AngleHorLimit=10.0/60.0
    endif
    // si DEC<30°: 20min supplémentaires -> 15min
    if DEC2000<0.5 then
        AngleHorLimit=15.0/60.0
    endif
    // si DEC<25°: 1h10 supplémentaires -> 20min
    if DEC2000<0.44 then
        AngleHorLimit=20.0/60.0
    endif
    // si DEC<6°: 1h45 supplémentaires -> 30 min
    if DEC2000>0.1 then
        AngleHorLimit=30.0/60.0
    endif

    if AngleHor>AngleHorLimit
       Now Date
       Datetostr Date Date$
       print "[" Date$ "] Target will be too close to meridian (telescope too close to pier) at the end of next exposure"
       ContinueObservations=0
       return
    endif

    // Check Sun elevation
    GetStdrLongitude Longitude
    GetStdrLatitude Latitude

    elevsunstartobservations=elevsunstartobservations_Deg/TODEG

    Now Date
    DateEndOfObs=Date+ExpSec/(3600.0*24.0)
    GETRADECSUN  DateEndOfObs  AlphaS  DeltaS  sunelevation
    Datetostr Date Date$
    Frac DateEndOfObs DateFrac
    RAD_TO_DEC sunelevation ElevationS$
    if sunelevation>elevsunstartobservations
       if DateFrac<0.5
          Now Date
          Datetostr Date Date$
          print "[" Date$ "] Sun too high to continue observing"
          ContinueObservations=0
          return
       endif
    endif

ContinueObservations=1
return


/////////////////////////////////////////////////////////////////////////////////
//
// Check if Sun is still below horizon limit, check if observations can continu...
//
/////////////////////////////////////////////////////////////////////////////////
IsSunStillBelow:

// Check Sun elevation
GetStdrLongitude Longitude
GetStdrLatitude Latitude

elevsunstopobservations=elevsunstopobservations_Deg/TODEG

Now Date
GETRADECSUN  Date  AlphaS  DeltaS  sunelevation
Datetostr Date Date$
Frac Date DateFrac
RAD_TO_DEC sunelevation ElevationS$
if sunelevation>elevsunstopobservations
    if DateFrac<0.5 then
        Now Date
        Datetostr Date Date$
        print "[" Date$ "] Sun too high to continue observing"
        SunStillBelow=1
        ContinueObservations=0
        return
    endif
endif

SunStillBelow=1
ContinueObservations=1

return



/////////////////////////////////////////////////////////////////////////////////
//
// Wait several minutes (for long waiting time)...
//
/////////////////////////////////////////////////////////////////////////////////

WaitForMinutes:
    //MinutesToWait=5

    str MinutesToWait MinutesToWait$

    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Start waiting for " MinutesToWait$ " minutes"

    Now DateBegin

    WaitForMinutesLoop:
    Now Date
    Ecart=(Date-DateBegin)*24.0*60.0
    if Ecart<MinutesToWait then
    goto WaitForMinutesLoop:
    endif

    Now Date
    Datetostr Date Date$

    print "[" Date$ "] Fin (MinutesToWait=" MinutesToWait ")"
return

/////////////////////////////////////////////////////////////////////////////////
//
// CATALOG / Look up for Object$ parameters in terms of single exposure time, Nb of exposures...
//
/////////////////////////////////////////////////////////////////////////////////
// Initially used (with longuer list), now using an external file with target list...

LookUpObject:

NbExposure=0

if Object$="QRVul" then
    objet$="hd192685"
    GExpTime=0.5
    ExpSec=1200
    NbExposure=3
endif

if Object$="V442And" then
    objet$="hd6226"
    GExpTime=0.75
    ExpSec=1200
    NbExposure=6
endif

return


/////////////////////////////////////////////////////////////////////////////////
//
// TakeObject: acquire spectra of Object$
//
/////////////////////////////////////////////////////////////////////////////////

TakeObject:
    GoSub LookUpObject:

    GExpTime=GExpTime*ExposureCloudFactor

    GoSub GoToTargetAndAcquisition:
    GoSub IsSunStillBelow:
    if SunStillBelow=0 then
        if StarToSynchForObject$="" then
            // Add synchronisation on a star there is needed (not really needed anymore)
        endif
        GoTo EndOfSession:
    endif
return


/////////////////////////////////////////////////////////////////////////////////
//
// Meteo.pgm: Sentinel weather station management (T.Lemoult)
//
/////////////////////////////////////////////////////////////////////////////////
// Note: doesn't work yet, to be improved later...

ReadMeteo:

    //Print "Donnees de la station meteo Sentinel:"
    pathSentinel$="C:\Users\ObsBE\Documents\Sentinel\Datas\infodata.txt"
    Open_FileTxt_For_Read fichier pathSentinel$

    for i=1 7
        ReadFileTXT fichier ligneDummy$
    next i

    ReadFileTXT fichier ligneTempExt$
    CUTSTR ligneTempExt$ "=" 2 out$
    val out$ TempExt

    ReadFileTXT fichier ligneHumidity$
    CUTSTR ligneHumidity$ "=" 2 out$
    val out$ Humidity
    //print "Humidity=" out$

    ReadFileTXT fichier ligneDummy$
    ReadFileTXT fichier ligneDummy$

    ReadFileTXT fichier ligneTempSkyIR$
    CUTSTR  ligneTempSkyIR$  "="  2  out$
    val out$ TempskyIR
    //print "TempskyIR=" out$

    ReadFileTXT fichier ligneTempDetectorIR$
    CUTSTR ligneTempDetectorIR$ "=" 2 out$
    val out$ TempDetectorIR
    //print "TempDetectorIR=" out$

    ReadFileTXT fichier ligneRainFall$
    CUTSTR ligneRainFall$ "=" 2 out$
    if Out$="No" then
            RainFall=0
            RainFall$="N"
    ELSE
            RainFall=1
            RainFall$="Y"
    ENDIF
    //print "RainFall=" out$

    ReadFileTXT fichier ligneWindSpeedGust$
    CUTSTR ligneWindSpeedGust$ "=" 2 out$
    val out$ WindSpeedGust
    //print "WindSpeedGust=" out$

    ReadFileTXT fichier ligneDummy$
    ReadFileTXT fichier ligneDummy$
    ReadFileTXT fichier ligneDummy$
    ReadFileTXT fichier ligneDummy$

    ReadFileTXT fichier ligneLightLevel$
    CUTSTR ligneLightLevel$ "=" 2 out$
    val out$ LightLevel
    //print "LightLevel=" out$

    tempCiel=TempSkyIR-TempExt
    STR tempCiel tempCiel$
    //print "calcul temperature ciel =" tempCiel$

    ////////////////////////
    if (tempCiel<LimitTempCiel) then
        if RainFall=0 then
            if LightLevel>LimitMagnitudeCiel
                BeauTemp=1
            ELSE
                BeauTemp=0
            ENDIF
        ELSE
            BeauTemp=0
        ENDIF
    ELSE
        BeauTemp=0
    ENDIF   

    // Beautemp est obtenus en regardant que la derniere valeur du  Sentinel.
    if BeauTemp=1 then
        CompteurBeauTemp=CompteurBeauTemp+1
    ELSE
        CompteurBeauTemp=0
    ENDIF

    // MeteoOK donne un résultat filtree..
    if CompteurBeauTemp>ValMinBelleMeteo then
    //    Print "Il fait beau depuis un moment.. On va pouvoir observer"
        MeteoOK=1
    else
        MeteoOK=0
        IF (BeauTemp=1) then
    //        Print "Si le beau temps se maintien, on pourra observer"
        ELSE
    //        Print "Il ne fait pas assez beau pour observer"
        ENDIF
    ENDIF

    CLOSEFILETXT  fichier
return


// Other weather function - to be improved/checked...
BoucleAttendBeauTemp:
    Now Date
    Datetostr Date Date$
    print "[" Date$ "] Waiting for good weather. Sky temp=" tempCiel$ " (" LimitTempCiel "), Rain=" RainFall$

    GOSUB ReadMeteo:
    DELAYBLOCK 60000
    if MeteoOK=0 THEN
        GOTO BoucleAttendBeauTemp:
    ENDIF

return


/////////////////////////////////////////////////////////////////////////////////
//
// calculating night's date (from A. Maury)
//
/////////////////////////////////////////////////////////////////////////////////
CalculateNightDate:

    NOW year month day hour minute second MS

    lengthmonth[1]=31
    REM bissextile years
    yearfrac=year/4
    frac yearfrac bissextile
    if bissextile=0 then
       lengthmonth[2]=29
    else
       lengthmonth[2]=28
    endif
    lengthmonth[3]=31
    lengthmonth[4]=30
    lengthmonth[5]=31
    lengthmonth[6]=30
    lengthmonth[7]=31
    lengthmonth[8]=31
    lengthmonth[9]=30
    lengthmonth[10]=31
    lengthmonth[11]=30
    lengthmonth[12]=31

    if hour<12 then
       if day=1 then
          if month=1 then
             year=year-1
             month=12
             day=31
          else
             month=month-1
          endif
          day=lengthmonth[month]
       else
          day=day-1
       endif
    endif

    str year year$

    str month month$
    if month<10 then
       month$="0"+month$
    endif

    str day day$
    if day<10 then
       day$="0"+day$
    endif

    CurrentDate$=year$+month$+day$
    DateStats$=day$+"/"+month$+"/"+year$
   
    // set directory to save file and copy CALIB files in
    sDirSave$="C:\Users\ObsBE\Documents\Acquisitions\"+CurrentDate$+"_eShel101_Atik460-1x1_38420_Revel\"

return



/////////////////////////////////////////////////////////////////////////////////
//
// Read my own Be Star Catalog + top target list (inspired from A. Maury)
//
/////////////////////////////////////////////////////////////////////////////////

ReadStarCatalog:
    // start with Be star catalog (my own one, selection among BeSS catalog)
    Open_FileTxt_For_Read StarCatalog StarCatalogFileName$
    numberofstarsintargetlist=0
    // Dummy (title) first line
    ReadFileTxt StarCatalog line$
    readnextline:
    ENDOFFILE StarCatalog result
    if result=FALSE then
       numberofstarsintargetlist=numberofstarsintargetlist+1
       REM we have not arrived till the end of the file
       ReadFileTxt StarCatalog line$
       REM we split the line
       CUTSTR line$ ";" 1 starname[numberofstarsintargetlist]$
       CUTSTR line$ ";" 2 myobjname[numberofstarsintargetlist]$
//       myobjname[numberofstarsintargetlist]$=starname[numberofstarsintargetlist]$
       CUTSTR line$ ";" 3 starRAH$
       CUTSTR line$ ";" 4 starRAM$
       CUTSTR line$ ";" 5 starDecD$
       CUTSTR line$ ";" 6 starDecM$
       CUTSTR line$ ";" 7 starFileName[numberofstarsintargetlist]$
       CUTSTR line$ ";" 8 starVMag$
       CUTSTR line$ ";" 9 starOTHPriority$
       CUTSTR line$ ";" 10 starBeSSPriority$
       CUTSTR line$ ";" 11 starExpTimeSec$
       CUTSTR line$ ";" 12 starNbExposure$
      
       val starRAH$ starRAH
       val starRAM$ starRAM
       val starDecD$ starDecD
       val starDecM$ starDecM
       starRA[numberofstarsintargetlist]=starRAH+(starRAM/60)
       if starDecD<0 then
          starDec[numberofstarsintargetlist]=starDecD-(starDecM/60)
       else
          starDec[numberofstarsintargetlist]=starDecD+(starDecM/60)
       endif
       val starVMag$ starVMag[numberofstarsintargetlist]
       // Calculate the typical guiding exposure time for a Be star with this VMag (empiric formulae!)
       PowerVal=starVMag[numberofstarsintargetlist]-4.0)/2.5
       Power 10.0 PowerVal
       starGuideExposureSec[numberofstarsintargetlist]=0.045*PowerVal*100.0*ExposureCloudFactor
       round starGuideExposureSec[numberofstarsintargetlist] starGuideExposureSec[numberofstarsintargetlist]
       starGuideExposureSec[numberofstarsintargetlist]=starGuideExposureSec[numberofstarsintargetlist]/100.0
       numberofimages[numberofstarsintargetlist]=0
       val starBeSSPriority$ starWeightBeSS[numberofstarsintargetlist]
       val starOTHPriority$ starWeightOTH[numberofstarsintargetlist]
       starWeightDistance[numberofstarsintargetlist]=0
       sortIndex[numberofstarsintargetlist]=numberofstarsintargetlist
       SortCriteria[numberofstarsintargetlist]=starWeightBeSS[numberofstarsintargetlist]+starWeightOTH[numberofstarsintargetlist]+starWeightDistance[numberofstarsintargetlist]
       val starExpTimeSec$ starExpTimeSec[numberofstarsintargetlist]
       val starNbExposure$ starNbExposure[numberofstarsintargetlist]

       goto readnextline:
    endif
    closefiletxt StarCatalog
//    print "number of stars in the target list : " numberofstarsintargetlist   

Return


/////////////////////////////////////////////////////////////////////////////////
//
// Calculate the distance from (RARef/DECRef) for all targets in Star Catalog & add a weight factor
//
/////////////////////////////////////////////////////////////////////////////////

CalculateDistanceStarCatalogToRef:

    for Temp_i=1 to numberofstarsintargetlist
        starDeltaRA=(starRA[Temp_i]-RARef)*15.0
        if starDeltaRA<-180.0 then
            starDeltaRA=starDeltaRA+360.0
        endif
        if starDeltaRA>180.0 then
            starDeltaRA=360.0-starDeltaRA
        endif
        starDeltaDEC=starDec[Temp_i]-DECRef
        starDistance=(starDeltaRA*starDeltaRA)+(starDeltaDEC*starDeltaDEC)
        sqr  starDistance starDistance
        if starDistance>MaximumStarDistanceToTelescope then
            starDistance=MaximumStarDistanceToTelescope
        endif
        // CarreNum=(MaximumStarDistanceToTelescope-starDistance)*(MaximumStarDistanceToTelescope-starDistance)
        // CarreDen=MaximumStarDistanceToTelescope*MaximumStarDistanceToTelescope
        // starWeightDistance[Temp_i]=300.0*CarreNum/CarreDen
        starWeightDistance[Temp_i]=300.0*(MaximumStarDistanceToTelescope-starDistance)/MaximumStarDistanceToTelescope
        round starWeightDistance[Temp_i] starWeightDistance[Temp_i]
        if starWeightDistance[Temp_i]<>0 then
            SortCriteria[Temp_i]=starWeightBeSS[Temp_i]*2+starWeightOTH[Temp_i]+starWeightDistance[Temp_i]
        else
            SortCriteria[Temp_i]=0
        endif
        // Avoid going above DEC limit
        if starDEC[Temp_i]>MaximumStarDEC then
            SortCriteria[Temp_i]=0
        endif
    next Temp_i

return



/////////////////////////////////////////////////////////////////////////////////
//
// Check the star catalog with elevation, distance to meridian+safety limit
//
/////////////////////////////////////////////////////////////////////////////////

CheckStarCatalogForVisibility:

    NOW Date

    for Temp_i=1 to numberofstarsintargetlist

        // GET_TELESCOPE_POSITION RA2000 DEC2000 Haut Azi AHor
        GETSTDRLONGITUDE Longitude
        GETSTDRLATITUDE Latitude
        RATemp=starRA[Temp_i]/12*PI
        DECTemp=starDEC[Temp_i]/180*PI
        GETHEIGHT RATemp DECTemp Date Longitude Latitude Hauteur
        // Hauteur en degrés
        Hauteur=Hauteur*TODEG

        if Hauteur<HauteurMin then
            SortCriteria[Temp_i]=0
        endif

        // TSL pour calculer angle horaire
        SIDERALTIME Date Longitude TSL
        // Angle horaire objet en radian :
        COMPUTEANGLEHOR TSL RATemp AngleHor
        //Angle horaire en heures décimales, on ajoute la moitié du temps de pose
        AngleHor=AngleHor*12/PI+(starExpTimeSec[Temp_i]*starNbExposure[Temp_i]/7200.0))

        AngleHorLimit=0.0
        // si DEC<45°: 10min supplémentaires /2
        if starDEC[Temp_i]<45 then
            AngleHorLimit=0.0/60.0
        endif
        // si DEC<30°: 15min supplémentaires /2
        if starDEC[Temp_i]<30 then
            AngleHorLimit=0.0/60.0
        endif
        // si DEC<25°: 20 supplémentaires /2
        if starDEC[Temp_i]<25 then
            AngleHorLimit=0.0/60.0
        endif
        // si DEC<6°: 30 supplémentaires /2
        if starDEC[Temp_i]<6 then
            AngleHorLimit=0.0/60.0
        endif

        if AngleHor>AngleHorLimit
            SortCriteria[Temp_i]=0
        endif

//        if Temp_i=133 then
//            print "DEBUG: AnleHor (V442 And)=" AngleHor
//            print "DEBUG: AnleHorLimit=" AngleHorLimit           
//            print "DEBUG: Haueur=" Hauteur
//            print "DEBUG: HauterMin=" HauteurMin
//            print "DEBUG RA=" RATemp
//            print "DEBUG RA=" DECTemp
//        endif
       
    next Temp_i
   
return


/////////////////////////////////////////////////////////////////////////////////
//
// Sort star catalog : sort my star catalog based on a weight criteria (usually sum of different criteria)
//
/////////////////////////////////////////////////////////////////////////////////

SortStarCatalog:
    // SortIndex[]: table of index to sort
    // numberofstarsintargetlist: number of index to sort
    // SortCriteria[]: criteria (numerical) to use to sort, from highest to lowest number




    // advance the position through the entire array
    //   (could do j < n-1 because single element is also min element)

    for Sort_j=1 to numberofstarsintargetlist

        // find the min element in the unsorted a[j .. n-1]
        // assume the min is the first element

        Sort_iMax=Sort_j

        // test against elements after j to find the smallest
        Sort_i_start=Sort_j+1
        for Sort_i=Sort_i_start to numberofstarsintargetlist

            // if this element is less, then it is the new minimum */
            if SortCriteria[SortIndex[Sort_i]]>SortCriteria[SortIndex[Sort_iMax]] then
                // found new maximum; remember its index
                Sort_iMax=Sort_i
            endif
        next Sort_i

        if (Sort_iMax<>Sort_j)
            SortTemp=SortIndex[Sort_j]
            SortIndex[Sort_j]=SortIndex[Sort_iMax]
            SortIndex[Sort_iMax]=SortTemp
        endif

    next NumeroObject

return



/////////////////////////////////////////////////////////////////////////////////
//
// Testing: read catalog, calculate distance to V442 And & sort by weighted criteria -> look for next target?
//
/////////////////////////////////////////////////////////////////////////////////
// DO NOT USE - FOR TESTING PURPOSES ONLY...

TestCatalogFunctions:
    GoSub ReadStarCatalog:

    print "number of stars in the target list : " numberofstarsintargetlist   

    // QR Vul
    RARef=20.0+15.0/60.0
    DECRef=25.0/35.0
    // lam Cyg
    RARef=20.78
    DECRef=36.48
    // V442 And
    RARef=1.05
    DECRef=47.63
    // lam Cyg
    RARef=20.78
    DECRef=36.48
    // 28 Cyg
    RARef=19.98
    DECRef=37.03

    GET_TELESCOPE_POSITION Alpha2000 Delta2000 Hauteur Azimuth AngleHor
    RARef=Alpha2000
    DECRef=Delta2000
       
    GoSub CalculateDistanceStarCatalogToRef:

    GoSub CheckStarCatalogForVisibility:

    GoSub SortStarCatalog:

    for Temp_i=1 to numberofstarsintargetlist
        Temp_j=SortIndex[Temp_i]
        Temp_Prio=SortCriteria[Temp_j]
        if Temp_Prio>-1 then
            print "Prio=" Temp_Prio " starname number : " Temp_i " is : " starFileName[Temp_j]$ " star RA in decimal : " starRA[Temp_j] " star Dec in decimal : " starDec[Temp_j] " Vmag=" starVMag[Temp_j] " Guiding Exp Time=" starGuideExposureSec[Temp_j] " BeSS=" starWeightBeSS[Temp_j] " MyPrio=" starWeightOTH[Temp_j] " Distance=" starWeightDistance[Temp_j]
        endif
    next Temp_i
    END
return


/////////////////////////////////////////////////////////////////////////////////
//
// ReadObsC2A - download ARASBeAm BeSS target files to get priorities from it/ Need wget.exe to work.
//
/////////////////////////////////////////////////////////////////////////////////

ReadObsC2A:
    execexternal "C:\Users\ObsBE\Documents\Acquisitions\CALIB\wget.exe" "http://arasbeam.free.fr/robot/ObsC2A.txt"

    ObsC2A$="C:\Users\ObsBE\Documents\Acquisitions\CALIB\ObsC2A.txt"

    Open_FileTxt_For_Read ObsC2A ObsC2A$
    NbObsC2A=0
    // Dummy (title) first line
    ReadFileTxt ObsC2A line$
    readnextline:
    ENDOFFILE ObsC2A result
    if result=FALSE then
        NbObsC2A=NbObsC2A+1
        REM we have not arrived till the end of the file
        ReadFileTxt ObsC2A line$
        REM we split the line
        Deb=16
        Fin=6
        SUBSTRING  line$  Deb  Fin  objet$
        print line$
        print objet$

       goto readnextline:
    endif
    closefiletxt ObsC2A

Return


/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//                                                                             END OF SCRIPT                                                                     //
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////


And the catalog that I use (just the first lines):

BeSSName;MyName;RA;RAm;DEC;DECm;FileName;VMag;OTHPriority;BeSSPriority;ExpSec;NbExposure
HD103287;gam Uma;+11;53;+53;41;gamUma;2.44;0;17;600;4
HD5394;gam Cas;+00;56;+60;43;gamCas;2.47;0;80;60;20
HD58715;bet CMi;+07;27;+08;17;betCMi;2.89;0;32;600;4
HD37202;zet Tau;+05;37;+21;08;zetTau;3.03;0;100;450;4
HD205021;ALFIRK;+21;28;+70;33;ALFIRK;3.22;0;100;600;4
HD11415;eps Cas;+01;54;+63;40;epsCas;3.34;0;3;450;3
HD35411;eta Ori;+05;24;-02;23;etaOri;3.38;0;100;600;4
HD174638;bet Lyr;+18;50;+33;21;betLyr;3.52;0;3;600;4
HD217675;omi And;+23;01;+42;19;omiAnd;3.63;100;2;800;4
HD166014;omi Her;+18;07;+28;45;omiHer;3.84;0;2;900;4
HD109387;kap Dra;+12;33;+69;47;kapDra;3.88;0;6;900;4
HD199629;nu Cyg;+20;57;+41;10;nuCyg;3.94;0;1;900;4
HD25940;48 Per;+04;08;+47;42;48Per;4;0;28;900;4
HD24912;xi Per;+03;58;+35;47;xiPer;4.06;0;100;900;4
HD10516;phi Per;+01;43;+50;41;phiPer;4.09;0;33;900;4
HD45542;nu Gem;+06;28;+20;12;nuGem;4.14;0;31;900;4
HD138749;tet CrB;+15;32;+31;21;tetCrB;4.15;0;24;900;3
HD6811;phi And;+01;09;+47;14;phiAnd;4.25;0;4;600;4
HD22192;psi Per;+03;36;+48;11;psiPer;4.31;0;55;900;3
HD30739;2 Ori;+04;50;+08;54;2Ori;4.35;0;34;900;6
HD202904;ups Cyg;+21;17;+34;53;upsCyg;4.43;0;1;600;4
HD98058;phi Leo;+11;16;-03;39;phiLeo;4.47;0;24;900;4
HD4180;omi Cas;+00;44;+48;17;omiCas;4.48;0;70;600;6
HD217891;bet Psc;+23;03;+03;49;betPsc;4.49;0;1;600;4
HD37490;ome Ori;+05;39;+04;07;omeOri;4.57;0;47;900;4
HD47839;15 Mon;+06;40;+09;53;15Mon;4.64;0;37;900;4
HD209409;omi Aqr;+22;03;-02;09;omiAqr;4.7;0;69;900;4
HD20336;BK Cam;+03;19;+65;39;BKCam;4.73;0;20;900;4
HD200120;59 Cyg;+20;59;+47;31;59Cyg;4.74;0;20;900;4
HD198183;lam Cyg;+20;47;+36;29;lamCyg;4.75;0;10;900;3
HD192685;QR Vul;+20;15;+25;35;QRVul;4.76;40;29;900;3
HD164284;66 Oph;+18;00;+04;22;66Oph;4.78;100;17;900;3
HD212571;pi Aqr;+22;25;+01;22;piAqr;4.79;60;100;600;4
HD212076;31 Peg;+22;21;+12;12;31Peg;4.81;0;5;1200;4
HD35439;25 Ori;+05;24;+01;50;25Ori;4.87;0;100;1200;4
HD187811;12 Vul;+19;51;+22;36;12Vul;4.89;0;8;1200;4
HD191610;28 Cyg;+20;09;+36;50;28Cyg;4.93;0;67;900;3
HD24479;HD24479;+03;57;+63;04;HD24479;4.95;0;26;1200;4
HD42545;69 Ori;+06;12;+16;07;69Ori;4.95;0;100;1200;4
HD52918;19 Mon;+07;02;-04;14;19Mon;4.99;0;44;1200;4






1 commentaire: