11 The visao python module provides a python intervace to the VisAO camera
13 The components of VisAO are combined in the VisAO class
16 from visaodevices
import *
19 def __init__(self, value):
22 return repr(self.
value)
25 def sigint_handler(signum, frame):
27 Handle SIGINT so that ctrl-c will interrup a script at any point
33 Class to control the VisAO Camera.
45 signal.signal(signal.SIGINT, sigint_handler)
47 print "********************************"
48 print "VisAO script control initialized"
49 print "********************************"
54 self.shutter.connect()
59 def take_control(self):
60 self.focus.take_control()
61 self.ccd47.take_control()
62 self.shutter.take_control(1)
63 self.fw2.take_control()
64 self.fw3.take_control()
66 def giveup_control(self):
67 self.focus.giveup_control()
68 self.ccd47.giveup_control()
69 self.shutter.giveup_control()
70 self.fw2.giveup_control()
71 self.fw3.giveup_control()
75 self.gimbal.take_control()
76 self.ccd47.write_fifoch(
'serve 0')
79 def setup(self, filter2, filter3):
80 self.fw2.set_filter(filter2)
81 self.fw3.set_filter(filter3)
87 resp = self.focus.wait_move()
89 raise "setup: Focus motor error. "
91 resp = self.fw2.wait_move()
93 raise "setup: F/W 2 motor error. "
95 resp = self.fw3.wait_move()
97 raise "setup: F/W 3 motor error. "
99 def take_darks(self, ndarks):
100 print "take_darks: taking %i darks" % ndarks
101 if self.shutter.get_state() != -1:
102 et = 1./self.ccd47.get_framerate()
103 print "take_darks: closing shutter"
113 if self.shutter.get_state() != -1:
114 raise "take_darks: could not close shutter"
116 print "take_darks: shutter closed"
119 self.ccd47.savedark(ndarks)
120 self.ccd47.wait_save()
122 print "take_darks: done"
124 def take_flats(self, nflt):
125 print "taking %i flats" % nflt
126 if self.shutter.get_state() != 1:
127 et = 1./self.ccd47.get_framerate()
128 print " exptime = %f" % et
129 print " opening shutter"
133 print " shutter open"
136 self.ccd47.save(nflt)
137 self.ccd47.wait_save()
140 def take_science(self, nsci):
141 print "take_science: taking %i science images" % nsci
142 if self.shutter.get_state() != 1:
143 et = 1./self.ccd47.get_framerate()
144 print "take_science: opening shutter"
154 if self.shutter.get_state() != 1:
155 raise "take_science: could not open shutter"
157 print "take_science: shutter open"
159 self.ccd47.savescience(nsci)
161 self.ccd47.wait_save()
163 print "take_science: done"
167 Take a linearity curve.
169 Takes darks and science frames at a sequence of exposure times.
171 nims = number of darks and science frames to take at each exposure time
172 etimes = exposure times, e.g. [.3, .5, .75, 1.0, 2.0, 3.0], in secs
174 print "starting linearity curve . . ."
175 sd = get_visao_filename_now(
"linearity_")
177 self.ccd47.subdir(sd)
183 for i
in range(len(etimes)):
184 print " step %i: " % i
185 self.ccd47.exptime(etimes[i])
187 et = 1./self.ccd47.get_framerate()
188 print " ccd47 exposure time set to %f" % et
192 print " linearity curve complete"
194 self.ccd47.subdir(
".")
196 def science(self, totexp, exptime, masterdarks, darkint, ndark, dirname="science", appendts=1, subroutine=0):
198 Take a science data set
200 Takes science images until a specified total exposure time is reached. Takes darks at intervals.
201 Other than exposure time, assumes camera is set up as you prefer.
203 totexp = total science exposure time, in seconds
204 exptime = exposure time of individual images, in seconds
205 masterdarks = number of darks to take at beginning of script
206 darkint = interval between dark sets, in seconds
207 ndark = number of dark frames to take
208 dirname = base name of directory to store images in, default is "science"
209 appendts = append the standard VisAO timestamp, default is 1 (yes). set to 0 for no.
214 exptime = 1/self.ccd47.get_framerate()
215 print "science: using current exposure time = %f" % exptime
217 nscitot = math.floor(totexp/exptime + 0.99999)
218 nsci = math.floor(darkint/exptime)
223 ndarksets = math.floor(nscitot/darkint)
226 sd = get_visao_filename_now(dirname)
230 print '\n**********************************************\n'
231 print ' Will take VisAO science data:'
232 print ' %i total science images, %f sec total science exposure' % (nscitot , (nscitot*exptime))
233 print ' in sets of %i images with %i darks in between' % (nsci , ndark)
234 print ' Total time = %f sec' % (nscitot*exptime + ndarksets*ndark*exptime)
235 print " Saving images to directory: %s" % sd
239 foo = raw_input(
'Proceed ? [y/n] (n): ')
244 print 'Proceeding . . .'
249 self.ccd47.subdir(sd)
253 resp = self.focus.wait_move()
255 raise "science: focus motor error. "
257 print "science: focus motor is focused."
260 set_subdir = self.ccd47.get_subdir()
261 if(set_subdir != sd):
263 set_subdir = self.ccd47.get_subdir()
264 if(set_subdir != sd):
267 raise "science: ccd47 subdirectory error"
270 self.ccd47.exptime(exptime)
273 if (masterdarks > 0):
276 for i
in range(
int(nscitot/nsci)):
283 nsci_taken = nsci_taken + nsci
286 nsci_taken = nscitot-nsci_taken
289 print '\n**********************************************\n'
290 print ' Completed taking VisAO science data:'
291 print ' %i total science images taken.' % nsci_taken
292 print '\n**********************************************\n'
294 self.ccd47.subdir(
"./")
299 visao_script_complete()
301 except Ctrl_C_Except:
305 self.ccd47.subdir(
"./")
309 visao_script_stopped()
310 print '******************\n science: script stopped\n******************\n'
315 self.ccd47.subdir(
"./")
319 print '******************\n science: something bad happened\n******************\n'
325 def observation(self, observations, repeats, subdir="", appendts=1):
329 if type(observations) != tuple:
330 raise "observation: invalid observation (must be tuple)"
337 if len(observations) == 11:
338 if type(observations[2])
is int:
341 nobs = len(observations)
343 nobs = len(observations)
348 if type(observations) != tuple:
349 raise "observation: invalid observation (must be tuple)"
351 if len(observations) != 11:
352 raise "observation: invalid observation (must have 11 elements)"
355 observations = (observations, observations)
357 for i
in range(nobs):
358 if type(observations[i]) != tuple:
359 raise "observation: invalid observation number %d (must be tuple)" % (i+1)
361 if len(observations[i]) != 11:
362 raise "observation: invalid observation number %d (must have 11 elements)" % (i+1)
365 subdir =
"observation"
368 sdbase = get_visao_filename_now(subdir)
382 for i
in range(nobs):
384 print "observation: Changing filter 2 to %s . . ." % observations[i][0]
385 resp = self.fw2.set_filter(observations[i][0])
386 print "observation: Changing filter 3 to %s . . ." % observations[i][1]
387 resp = self.fw3.set_filter(observations[i][1])
392 print "observation: Moving to focus preset"
395 print "observation: Programming CCD 47"
396 etime = observations[i][5]
397 minetime = getCCD47MinExp(observations[i][2],observations[i][3],1)
400 self.ccd47.set_program(observations[i][2],observations[i][3],observations[i][4], etime)
405 resp = self.focus.wait_move()
406 resp2 = self.fw2.wait_move()
407 resp3 = self.fw3.wait_move()
410 filt2 = self.fw2.get_filter()
411 filt3 = self.fw3.get_filter()
413 if filt2 != observations[i][0]:
414 raise "observation: filter 2 not correct"
416 if filt3 != observations[i][1]:
417 raise "observation: filter 3 not correct"
420 raise "observation: focus motor error"
422 print "observation: In filters %s and %s, and in focus" % (filt2, filt3)
425 if(observations[i][10] ==
""):
426 filtname2 = filt2.replace(
" ",
"_")
427 filtname2 = filtname2.replace(
"'",
"p")
429 filtname3 = filt3.replace(
" ",
"_")
430 filtname3 = filtname3.replace(
"'",
"p")
432 sd =
"%s/%s_%s_%d" % (sdbase, filtname2, filtname3,i)
434 sd =
"%s/%s_%d" % (sdbase, observations[i][10], (ntimes+1))
438 self.
science(observations[i][6], etime, observations[i][7], observations[i][8], observations[i][9], sd, 0, 1)
443 if ntimes >= repeats
and repeats > 0:
447 print '\n**********************************************\n'
448 print ' Completed VisAO observation:'
450 print '\n**********************************************\n'
452 self.ccd47.subdir(
"./")
456 visao_script_complete()
458 except Ctrl_C_Except:
461 visao_script_stopped()
462 print '******************\n observation: script stopped\n******************\n'
468 print '******************\n observation: something bad happened\n******************\n'
474 def dither(self, dx, dy, ims, ndarks, subdir="", appendts=1, giveup=1):
476 Take data in a dither pattern.
478 Takes darks at the beginning, then takes science images at each gimbal position specified in dx,dy.
480 dx = gimbal x positions (mm)
481 dy = gimbal y positions (mm)
482 ims = number of science images to take at each position.
483 ndarks = number of drks to take at the beginning
484 subdir = optional subdirectory. if not specified, then dither_[timestamp] will be used
485 appendts = append the standard VisAO timestamp, default is 1 (yes). set to 0 for no.
486 giveup = if set 1 one, then control will be taken and given up at the end of the dither
494 self.gimbal.take_control()
497 subdir = get_visao_filename_now(
"dither_")
500 subdir = get_visao_filename_now(subdir)
503 self.ccd47.subdir(subdir)
510 startx = self.gimbal.get_xpos()
511 starty = self.gimbal.get_ypos()
515 resp = self.focus.wait_move()
517 raise "dither: focus motor error. "
519 print "dither: focus motor is focused."
522 print "dither: Saving %i darks" % (ndarks)
526 print "dither: saving %i images at dither 1/%i" % (ims, len(dx))
530 for i
in range(len(dx)):
531 print "dither: moving to pos %i/%i: %f %f . . ." % (i+1,len(dx), dx[i] , dy[i])
532 rv = self.gimbal.move_xrel(dx[i])
534 raise "dither: error during x dither. Halting."
536 rv = self.gimbal.move_yrel(dy[i])
538 raise "dither: error during y dither. Halting."
540 rv = self.gimbal.wait_move()
542 raise "dither: error during dither. Halting."
545 et = 1./self.ccd47.get_framerate()
548 print "dither: saving %i images at dither %i/%i" % (ims, i, len(dx))
552 print "dither: returning to start positions"
554 rv = self.gimbal.move_xabs(startx)
556 raise "dither: error during x move. Halting."
558 rv = self.gimbal.move_yabs(starty)
560 raise "dither: error during y move. Halting."
562 rv = self.gimbal.wait_move()
564 print "raise: error during dither. Halting."
566 self.ccd47.subdir(
".")
568 self.gimbal.giveup_control()
572 visao_script_complete()
574 except Ctrl_C_Except:
584 visao_script_stopped()
585 print '******************\n dither: script stopped\n******************\n'
593 print '******************\n dither: something bad happened\n******************\n'
596 def dither_phot(self, filters, nims, ndarks, dx, dy, subdir="", appendts=1):
598 Take data in a dither pattern in multiple filters.
600 Takes darks at the beginning of each filter, then takes science images at each gimbal position specified in dx,dy.
601 Then changes filters and repeats. Focus stage is moved to appropriate preset after each filter change.
603 filters = list of filters to cycle through
604 nims = the number of science images to take in each dither position per filter
605 ndarks = the number of initial darks to take
606 dx = gimbal x offsets from initial position, in mm
607 dy = gimbal y offsets from initial position, in mm
608 subdir = optional subdirectory. if not specified, then dither_[timestamp] will be used
609 #appendts = append the standard VisAO timestamp, default is 1 (yes). set to 0 for no.
613 subdir =
"phot_dither"
616 sdbase = get_visao_filename_now(subdir)
623 for i
in range(len(filters)):
625 print "Changing filter to %s . . ." % filters[i]
626 resp = self.fw2.set_filter(filters[i])
629 print "Moving to focus preset . . ."
632 resp = self.fw2.wait_move()
634 filt = self.fw2.get_filter()
636 print "In filter %s . . ." % filt
638 if filt!= filters[i]:
639 print "Filter not correct."
643 print "Focus motor error. "
646 self.focus.wait_move()
648 filtname = filt.replace(
" ",
"_")
649 filtname = filt.replace(
"'",
"p")
651 sd =
"%s/%s" % (sdbase, filtname)
654 self.
dither(dx, dy, nims, ndarks, sd, 0,0)
657 visao_script_complete()
659 except Ctrl_C_Except:
666 visao_script_stopped()
667 print '******************\n dither_phot: script stopped\n******************\n'
675 print '******************\n dither_phot: something bad happened\n******************\n'
678 def flats_old(self, totexp, exptime, ndark, dirname="flats"):
680 nsci = math.floor(totexp/exptime + 0.99999)
683 sd = get_visao_filename_now(dirname)
686 print '\n**********************************************\n'
687 print ' Will take VisAO flats data:'
688 print ' %i total flats per filter, %f sec total flat exposure' % (nsci, (nsci*exptime))
689 print ' With %i darks in between' % (ndark)
690 print " Saving images to directory: %s" % sd
692 foo = raw_input(
'Proceed ? [y/n] (n): ')
697 print 'Proceeding . . .'
698 self.ccd47.subdir(sd)
700 self.ccd47.exptime(exptime)
712 self.fw2.set_filter(filters[0])
714 for n
in range(len(nds)):
715 print "Changing ND to %s . . ." % nds[n]
716 resp = self.fw3.set_filter(nds[n])
718 resp = self.fw3.wait_move()
720 ndn = self.fw3.get_filter()
722 print "In ND %s . . ." % ndn
725 print "ND not correct."
728 for i
in range(len(filters)):
729 print "Changing filter to %s . . ." % filters[i]
730 resp = self.fw2.set_filter(filters[i])
732 resp = self.fw2.wait_move()
734 filt = self.fw2.get_filter()
736 print "In filter %s . . ." % filt
738 if filt!= filters[i]:
739 print "Filter not correct."
744 visao_script_complete()
748 print '******************\nSomething bad happened\n******************\n'
755 Take a telemetry data set with simultaneous focal plane data. Takes fast frames and slow frames
757 tottime = total time of the measurement in seconds
758 fast_darks = number of fast darks to take
759 slow_darks = number of slow dards to take
761 pset = the program set. pset=0 means 1024 and 64, pset=1 means 512 and 32
766 fast_set =
'set 0 1 0 0'
767 slow_set =
'set 0 0 0 0'
770 fast_set =
'set 1 1 0 0'
771 slow_set =
'set 1 0 0 0'
781 self.bcu39.take_control()
788 resp = self.focus.wait_move()
790 print "Focus motor error. "
794 self.ccd47.write_fifoch(fast_set)
797 self.ccd47.exptime(exptime_s)
800 f = get_visao_filename_now(
'shuttercal_short')
801 self.ccd47.subdir(
'47_' + f)
802 self.fw39.take_control(1)
803 self.fw39.subdir(
'39_' + f)
817 self.ccd47.write_fifoch(slow_set)
821 f = get_visao_filename_now(
'shuttercal_long')
822 self.ccd47.subdir(
'47_' + f)
823 self.fw39.take_control(1)
824 self.fw39.subdir(
'39_' + f)
836 visao_script_complete()
839 def take_ron(self, nf2500, nf250, nf80):
845 print '******************\n2500 kHz, 1024x1024, 1x1, gain 0\n******************\n'
846 self.ccd47.write_fifoch(
'set 0 0 0 0')
847 sd = get_visao_filename_now(
"ron2500_g0")
848 self.ccd47.subdir(sd)
850 self.ccd47.save(nf2500, 2)
851 self.ccd47.wait_save()
854 print '******************\n2500 kHz, 1024x1024, 1x1, gain 1\n******************\n'
855 self.ccd47.write_fifoch(
'set 0 0 1 0')
856 sd = get_visao_filename_now(
"ron2500_g1")
857 self.ccd47.subdir(sd)
859 self.ccd47.save(nf2500, 2)
860 self.ccd47.wait_save()
863 print '******************\n2500 kHz, 1024x1024, 1x1, gain 2\n******************\n'
864 self.ccd47.write_fifoch(
'set 0 0 2 0')
865 sd = get_visao_filename_now(
"ron2500_g2")
866 self.ccd47.subdir(sd)
868 self.ccd47.save(nf2500, 2)
869 self.ccd47.wait_save()
872 print '******************\n2500 kHz, 1024x1024, 1x1, gain 3\n******************\n'
873 self.ccd47.write_fifoch(
'set 0 0 3 0')
874 sd = get_visao_filename_now(
"ron2500_g3")
875 self.ccd47.subdir(sd)
877 self.ccd47.save(nf2500, 2)
878 self.ccd47.wait_save()
882 print '******************\n250 kHz, 1024x1024, 1x1, gain 0\n******************\n'
883 self.ccd47.write_fifoch(
'set 0 2 0 0')
884 sd = get_visao_filename_now(
"ron250_g0")
885 self.ccd47.subdir(sd)
887 self.ccd47.save(nf250, 2)
888 self.ccd47.wait_save()
891 print '******************\n250 kHz, 1024x1024, 1x1, gain 1\n******************\n'
892 self.ccd47.write_fifoch(
'set 0 2 1 0')
893 sd = get_visao_filename_now(
"ron250_g1")
894 self.ccd47.subdir(sd)
896 self.ccd47.save(nf250, 2)
897 self.ccd47.wait_save()
900 print '******************\n250 kHz, 1024x1024, 1x1, gain 2\n******************\n'
901 self.ccd47.write_fifoch(
'set 0 2 2 0')
902 sd = get_visao_filename_now(
"ron250_g2")
903 self.ccd47.subdir(sd)
905 self.ccd47.save(nf250, 2)
906 self.ccd47.wait_save()
909 print '******************\n250 kHz, 1024x1024, 1x1, gain 3\n******************\n'
910 self.ccd47.write_fifoch(
'set 0 2 3 0')
911 sd = get_visao_filename_now(
"ron250_g3")
912 self.ccd47.subdir(sd)
914 self.ccd47.save(nf250, 2)
915 self.ccd47.wait_save()
919 print '******************\n80 kHz, 1024x1024, 1x1, gain 0\n******************\n'
920 self.ccd47.write_fifoch(
'set 0 4 0 0')
921 sd = get_visao_filename_now(
"ron80_g0")
922 self.ccd47.subdir(sd)
924 self.ccd47.save(nf80, 2)
925 self.ccd47.wait_save()
928 print '******************\n80 kHz, 1024x1024, 1x1, gain 1\n******************\n'
929 self.ccd47.write_fifoch(
'set 0 4 1 0')
930 sd = get_visao_filename_now(
"ron80_g1")
931 self.ccd47.subdir(sd)
933 self.ccd47.save(nf80, 2)
934 self.ccd47.wait_save()
937 print '******************\n80 kHz, 1024x1024, 1x1, gain 2\n******************\n'
938 self.ccd47.write_fifoch(
'set 0 4 2 0')
939 sd = get_visao_filename_now(
"ron80_g2")
940 self.ccd47.subdir(sd)
942 self.ccd47.save(nf80, 2)
943 self.ccd47.wait_save()
946 print '******************\n80 kHz, 1024x1024, 1x1, gain 3\n******************\n'
947 self.ccd47.write_fifoch(
'set 0 4 3 0')
948 sd = get_visao_filename_now(
"ron80_g3")
949 self.ccd47.subdir(sd)
951 self.ccd47.save(nf80, 2)
952 self.ccd47.wait_save()
def take_linearity(self, nims, etimes)
def take_flats(self, nflt)
def take_science(self, nsci)
def take_darks(self, ndarks)