aposong module

aposong provides a Python interface to the observing system for the SONG node at Apache Point Observatory. It communicates with devices attached to other computers on the internal APO network: the Planewave 1m telescope, the Planewave mirror covers, the focal plane unit and camera on the telescope, the dome, a safety monitor that checks status of other telescopes on site, and, eventually, a spectrograph camera.

Communication with these devices is achieved, for the most part, using the ASCOM/Alpaca protocol, although a few more specialized commands are communicated through non-standard interfaces (Planewave has an API that provides more functionality than their ACSCOM driver).

The main module, aposong, opens up an Alpaca device for each of the devices. It provides routines for many basic observatory tasks, e.g., opening and closing, slewing, taking exposures, etc., coordinating commands to different devices as needed. Individual devices can also be addressed using the Alpaca device instantiations and the standard ASCOM command sets for more experienced users if needed.

It can be used to run an interactive Python client. To run the software, simply issue

aposong

This will start an ipython client, load appropriate modules and commands, and instantiate a pyvista TV tool into the variable, disp.

Commands

Information about individual commands and parameters is best obtained through the docstrings, available below or using interactive help when running the Python interface, but a summary of commands is:

Observatory commands:
  • domeopen(): open dome, mirror covers

  • domeclose(): close mirror covers, dome, and park

  • issafe(): check safety moniotor for status

Dome commands:
  • domehome(): move dome to home position

  • domesync(True|False) : starts/stops thread to sync dome to telescope position

  • louvers(True|False) : open/close louvers

Telescope commands :
  • slew(ra,dec): slew to coordinates

  • offset(dra,ddec): offset telescope in ra/dec

  • offsetxy(dx,dy): offset telescope in detector coordinates

  • usno([ra,dec]) : find/slew to USNO A2.0 star

  • altaz(az,alt): slew to az/alt coordinates

  • foc(focus) : set focus to specified value

  • tracking(True|False): turn tracking on/off

  • mirror_covers(True|False): control mirror covers

  • fans(True|False): control telescope fans

  • port(port): move tertiary to requested port

  • park(): park telescope and dome

Camera commands :
  • expose(exptime,filt,**kwargs): take an exposure, returns named Exposure tuple with data, hdu, etc.

  • gexp(exptime,**kwargs): take an exposure with guide camera binned 1x1 (frontend to expose())

  • sexp(exptime,**kwargs): take an exposure with spectrograph camera binned 2x2 (frontend to expose())

  • focrun(cent,step,nsteps,exptime,filt,**kwargs): take series of exposures at different focus positions

  • settemp(temp): set camera temperature set point

  • cooler(state): set camera cooler state on (True) or off (False)

  • chiller([temp]): get/set chiller temperature

  • chiller_fault(): get chiller fault status

Focal plane unit commands :
  • iodine_position([val]) : get or set (with val) iodine stage position

  • iodine_tset(val) : set iodine temperature (both channels)

  • iodine_tget(): get actual iodine temperatures

  • iodine_home : home iodine stage

  • iodine_tset(val) : set iodine temperature (both channels)

  • iodine_tget(): get actual iodine temperatures

  • iodine_get(quantity): get various TC300 values (tset,voltage,current,enable,dark,light)

Calibration commands :
  • calstage_in() : move calibration stage into beam, and adjust focus (if needed)”

  • calstage_out() : move calibration stage out of beam, and adjust focus (if needed)

  • calstage_position([val]) : get or set (with val) iodine stage position

  • calstage_home : home iodine stage

  • cal.getlamps() : get eShel lamp status

  • cal.lamps() : control eShel lamps

  • cal.cals() : turn lamps on, take sequences of flats and ThAr, turn lamps off

  • cal.shutter() : open/close shutter in direct calibration feed

Alpyca devices

Importing aposong exposes several Alpyca devices as Python objects:

  • T : Telescope device

  • F[] : Focuser devices : Planewave focuser (ASCOM) , Zaber focuser (Alpaca) , iodine stage (Alpaca)

  • C[] : Camera devices : Port 1 QSI camera (ASCOM), Port 2 acquisition camera (ASCOM), Port 2 Shelyak camera (ASCOM)

  • Covers : Covercalibrator device :Planewave mirror covers (ASCOM)

  • D : Dome device : APOAshDome Alpaca device

  • S : Safetymonitor device : APOSafety Alpaca device

  • SW[] : Switch devices : Thorlabs TC300 temperature controller (Alpaca), Shelyak calibration unit (Alpaca)

Configuration

Some basic configuration is done using the aposong.yml file. This file configures the IP addresses for the ASCOM Remote servers, the PWI4 server.

Module functions

class aposong.Exposure(hdu, name, exptime, filter)
exptime

Alias for field number 2

filter

Alias for field number 3

hdu

Alias for field number 0

name

Alias for field number 1

class aposong.DomeStatus(shutterstate, az, slewing, lights)
az

Alias for field number 1

lights

Alias for field number 3

shutterstate

Alias for field number 0

slewing

Alias for field number 2

aposong.getcam(camera=None)[source]

Get correct list index for specified camera (ASCOM doesn’t always deliver them in order!) camera=0 : Port 2 camera camera=1 : Port 2 spectrograph camera (eShel) camera=2 : Port 1 camera (QSI) camera=3 : SONG spectrograph camera

aposong.getfocuser(focuser)[source]

Get correct list index for specified focuser (ASCOM doesn’t always deliver them in order!) focuser=’PWI’ : Port 1 focuser (PWI) focuser=’Zaber’ : Port 2 focuser (Zaber) focuser=’Iodine’ : Port 2 iodine stage (LTS150) focuser=’Calibration’ : Port 2 calibration stage (LTS150) focuser=’PLL’ : Spectrograph focus (PrimaLuceLab Esatto 3.5”)

aposong.getswitch(switch)[source]

Get correct list index for specified switch (ASCOM doesn’t always deliver them in order!) switch=’TC300’ : Thorlabs temperature controller switch=’K8056’ : relay for Shelyak calibration control switch=’LCUS’ : LCUS relay for calibration shutter switch=’Yocto’ : Thermocouples on QHY600 switch=’Wanderer’ : Wanderer PowerBox for spectrograph CCD and focuser USB reset switch=’TCube’ : TCube chiller

aposong.wait_moving(Foc)[source]

Check if input Focuser is stil moving

aposong.qck(exptime, filt='current')[source]

(shorthand) Take exposure without saving to disk, current filter by default

aposong.gexp(*args, **kwargs)[source]

Expose with guide camera, see expose() for keywords

Parameters:
  • exptime (float) – Exposure time in seconds

  • bin (int, default=1) – binning factor (both x and y)

  • display (pyvista tv, default=None) – pyvista display tool to display into if specified

  • name (str, default=None) – root file to save image to

aposong.sexp(*args, **kwargs)[source]

Expose with spectrograph camera, see expose() for keywords

Parameters:
  • exptime (float) – Exposure time in seconds

  • bin (int, default=2) – binning factor (both x and y)

  • display (pyvista tv, default=None) – pyvista display tool to display into if specified

  • name (str, default=None) – root file to save image to

aposong.expose(exptime=1.0, filt='current', bin=3, box=None, light=True, display=None, name=None, min=None, max=None, cam=0, insert=True, targ=None, avg=1, imagetyp='unspecified', header=None, fast=False)[source]

Take an exposure with camera

Parameters:
  • exptime (float) – Exposure time in seconds

  • filt (str) – Name of filter

  • bin (int, default=3) – binning factor (both x and y)

  • box (pyvista BOX, default=None) – if specified, window to box parameters

  • light (bool, default=True) – open shutter for exposure?

  • display (pyvista tv, default=None) – pyvista display tool to display into if specified

  • name (str, default=None) – root file to save image to

Returns:

named tuple

Return type:

Exposure = namedtuple(‘Exposure’, [‘hdu’, ‘name’, ‘exptime’, ‘filter’])

aposong.settemp(temp, cam=0)[source]

Change detector temperature set point and turn cooler on

aposong.chiller(temp=None)[source]

Get/set chiller temperature

aposong.chiller_fault(temp=None)[source]

Get chiller fault status

aposong.cooler(state=True, cam=0)[source]

Set detector cooler state on/off

aposong.filtname()[source]

Return current filter name

aposong.focrun(cent, step, n, exptime=1.0, filt='V', bin=3, box=None, display=None, max=30000, thresh=25, cam=0, plot=False)[source]

Obtain a focus run

Parameters:
  • cent (int) – Middle focus value

  • step (int) – Focus step size

  • n (int) – Number of steps to take, centered on middle value

  • exptime (float) – Exposure time

  • filt (str) – Filter to use

  • bin (int, default=3) – Binning factor in x and y

  • box (pyvista BOX, default=None) – if specified, window to box parameters

  • disp (pyvista tv, default=None) – If given, display each image as it is being taken into specified device

Return type:

List of file names taken for focus run

aposong.pixscale(cam=0, bin=1)[source]

Return pixscale for desired camera

aposong.telescope_status()[source]

Return telescope status

aposong.slew(ra, dec, dome=True)[source]

Slew to RA/DEC and wait for telescope/dome

Parameters:
  • ra (float or str) – RA in hours (float), or hh:mm:ss (str)

  • dec (float or str) – DEC in degrees (float), or dd:mm:ss (str)

aposong.altaz(az, alt)[source]

Slew to specified az / alt :param az: az in degrees :type az: float :param alt: alt in degrees :type alt: float

aposong.usno(ra=None, dec=None, rad=<Quantity 1. deg>, mag='Rmag', magmin=0, magmax=20, goto=True, cat='I/252')[source]

Find/goto nearest USNO stars from specified position (default current telescope) and mag range

Parameters:
  • ra (str or float, default=None) – RA to search around, default current telescope position

  • dec (str or float, default=None) – DEC to search around, default current telescope position

  • rad (angular quantity, default = 1*u.degree) – Radius to use for sear4ch

  • bmin (float, default=(0,15)) – Minimum, maximum Bmag

  • bmax (float, default=(0,15)) – Minimum, maximum Bmag

  • rmin (float, default=(0,15)) – Minimum, maximum Rmag

  • rmax (float, default=(0,15)) – Minimum, maximum Rmag

  • goto (bool, default=True) – If True, slew to closest returned object

  • cat (str, default= 'The USNO-A2.0 Catalogue 1') – astroquery conesearch catalog to search from hr=V/50, sao=I/131A/sao (but doesn’t have J2000)

aposong.center(display, x0=None, y0=None, exptime=5, bin=1, filt=None, settle=3, cam=0)[source]

Center star

aposong.guide(cmd, verbose=True, **kwargs)[source]

Send command to guider process

aposong.offsetxy(dx, dy, sign=-1, scale=0.16, pa=None)[source]

Offset in detector coordinates

aposong.offset(dra, ddec)[source]

One or more of the following offsets can be specified as a keyword argument:

AXIS_reset: Clear all position and rate offsets for this axis. Set this to any value to issue the command. AXIS_stop_rate: Set any active offset rate to zero. Set this to any value to issue the command. AXIS_add_arcsec: Increase the current position offset by the specified amount AXIS_set_rate_arcsec_per_sec: Continually increase the offset at the specified rate

As of PWI 4.0.11 Beta 7, the following options are also supported: AXIS_stop: Stop both the offset rate and any gradually-applied commands AXIS_stop_gradual_offset: Stop only the gradually-applied offset, and maintain the current rate AXIS_set_total_arcsec: Set the total accumulated offset at the time the command is received to the specified value. Any in-progress rates or gradual offsets will continue to be applied on top of this. AXIS_add_gradual_offset_arcsec: Gradually add the specified value to the total accumulated offset. Must be paired with AXIS_gradual_offset_rate or AXIS_gradual_offset_seconds to determine the timeframe over which the gradual offset is applied. AXIS_gradual_offset_rate: Paired with AXIS_add_gradual_offset_arcsec; Specifies the rate at which a gradual offset should be applied. For example, if an offset of 10 arcseconds is to be applied at a rate of 2 arcsec/sec, then it will take 5 seconds for the offset to be applied. AXIS_gradual_offset_seconds: Paired with AXIS_add_gradual_offset_arcsec; Specifies the time it should take to apply the gradual offset. For example, if an offset of 10 arcseconds is to be applied over a period of 2 seconds, then the offset will be increasing at a rate of 5 arcsec/sec.

Where AXIS can be one of: ra: Offset the target Right Ascension coordinate dec: Offset the target Declination coordinate axis0: Offset the mount’s primary axis position

(roughly Azimuth on an Alt-Az mount, or RA on In equatorial mount)

axis1: Offset the mount’s secondary axis position

(roughly Altitude on an Alt-Az mount, or Dec on an equatorial mount)

path: Offset along the direction of travel for a moving target transverse: Offset perpendicular to the direction of travel for a moving target

aposong.j2000totopocentric(ra, dec)[source]

Routine to convert J2000 coordinates to topocentric RA/DEC

aposong.rotator(offset=90.0)[source]

Get current rotator position angle, from parallactic angle and altitude for port 2 and telescope status for port 1

Parameters:

offset (float, default=100) – Angle constant (degrees) that needs to be set depending on camera/fixed rotator position for port 2

aposong.tracking(tracking)[source]

Set telescope tracking on (True) or off (False)

Parameters:

tracking (bool) – if True, turn tracking on, if False, turn tracking off

aposong.park()[source]

Park telescope and dome

aposong.foc_home(port=None)[source]

Send focus to home

aposong.foc(val=None, relative=False, port=None)[source]

Change focus, depending on port

aposong.specfoc(val=None)[source]

Change spectrograph focus

aposong.iodine_tset(val=None, tmax=66)[source]

Get/set iodine cell set temperature and (re)enable heaters

aposong.iodine_tget()[source]

Get/set iodine cell actual temperature

aposong.iodine_set(quantity, val)[source]

Miscellaneous TC300 commands: enable, dark, light

aposong.iodine_get(quantity)[source]

Get iodine cell quantity

aposong.iodine_in(val=None, focoffset=None)[source]

Move iodine cell into beam

aposong.iodine_out(val=None, focoffset=None)[source]

Move iodine cell out of beam

aposong.iodine_home()[source]

Send iodine stage to home

aposong.iodine_position(val=None)[source]

Get/set iodine stage position

aposong.calstage_home()[source]

Send calibration stage to home

aposong.calstage_position(val=None)[source]

Get/set calibration stage position

aposong.calstage_in(val=None, calfoc=None)[source]

Move calibration stage into beam

aposong.calstage_out(val=None)[source]

Move calibration stage out of beam

aposong.calstage_find(display=None)[source]

Find calibration spot location

aposong.fans_on(roles=None)[source]

Turn on PWI fans

Parameters:
  • roles (if None, turn on all fans)

  • Otherwise – m1rear: Primary mirror fans (rear fans only) m1side: Primary mirror fans (side fans only) m2: Secondary mirror fans m3: M3 mirror fans m1heaters: Primary mirror heat distribution fans

  • on (can be a CSV string of one or more fan roles to turn) – m1rear: Primary mirror fans (rear fans only) m1side: Primary mirror fans (side fans only) m2: Secondary mirror fans m3: M3 mirror fans m1heaters: Primary mirror heat distribution fans

aposong.fans_off(roles=None)[source]

Turn off PWI fans

aposong.port(port)[source]

Change PWI M3 port

aposong.mirror_covers(open=False)[source]

Open/close mirror covers

aposong.louvers(open=False)[source]

Open louvers

aposong.issafe()[source]

Query SafetyMonitor for safe to open

aposong.override(t, verbose=True)[source]

Set override to allow open

aposong.domestatus()[source]

Return dome azimuth and shutter status

aposong.domehome()[source]

Home dome

aposong.domeopen(dome=True, covers=True, fans=True, louvers=False)[source]

Open dome, mirror covers, louvers and start fans, as requested

aposong.domeclose(dome=True, covers=True, fans=True, closelouvers=True)[source]

Close mirror covers and dome

aposong.domesync(dosync=True, manual=False)[source]

Start/stop domesync thread

aposong.start_status(camera=True)[source]

Start status window thread

aposong.stop_status()[source]

Stop status window thread

aposong.devices()[source]

List connected ASCOM devices

aposong.init()[source]

Start ascom and pwi connections and pyvista display

aposong.disp_init()[source]

Start display with good geometry

aposong.alert(message, loggers=None, recipients=None)[source]

Print alert, and log and email as requeste3d

aposong.isguideok(ok, loggers=None, recipients=None)[source]

Check to see if guider is responding, if not send alert/log as requested (if a state change)

Parameters:
  • ok (bool) – current state of guider going into call

  • loggers (logger or list of loggers, default=None) – loggers to send message not

  • recipients (list of addresses, default=None) – addresses to send alerts to, if specified