Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Tammo Jan Dijkema
telescope
Commits
336a023b
Commit
336a023b
authored
Mar 25, 2018
by
Tammo Jan Dijkema
Browse files
Start big refactor into proper python
parent
f354062a
Changes
2
Hide whitespace changes
Inline
Side-by-side
setup.py
View file @
336a023b
#!/usr/bin/env python
from
setuptools
import
setup
,
find_packages
from
setuptools
import
setup
meta
=
dict
(
name
=
'telescope'
,
version
=
'1.1.1'
,
author
=
'Tammo Jan Dijkema'
,
author_email
=
'T.J.Dijkema@camras.nl'
,
url
=
'https://gitlab.camras.nl/dijkema/telescope'
,
description
=
'Software for the CAMRAS Dwingeloo Radio Telescope'
,
platforms
=
'Linux, Mac OSX'
,
py_modules
=
[
'telescope'
],
include_package_data
=
True
,
data_files
=
[(
''
,
[
'telescope.ini'
,]),],
install_requires
=
[
'astropy'
,
'configparser'
,
'numpy'
]
meta
=
dict
(
name
=
'telescope'
,
version
=
'1.1.1'
,
author
=
'Tammo Jan Dijkema'
,
author_email
=
'T.J.Dijkema@camras.nl'
,
url
=
'https://gitlab.camras.nl/dijkema/telescope'
,
description
=
'Software for the CAMRAS Dwingeloo Radio Telescope'
,
platforms
=
'Linux, Mac OSX'
,
py_modules
=
[
'telescope'
],
include_package_data
=
True
,
data_files
=
[(
''
,
[
'telescope.ini'
,]),
],
install_requires
=
[
'astropy'
,
'configparser'
,
'numpy'
]
)
setup
(
**
meta
)
telescope.py
View file @
336a023b
...
...
@@ -2,17 +2,16 @@ from __future__ import print_function
import
socket
import
logging
from
astropy.coordinates
import
SkyCoord
,
AltAz
,
RangeError
from
astropy
import
units
as
u
from
astropy.coordinates
import
SkyCoord
,
RangeError
from
configparser
import
ConfigParser
import
astropy.units
as
u
import
os.path
import
numpy
as
np
import
threading
import
select
import
time
config
=
ConfigParser
()
config
.
read
fp
(
open
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'telescope.ini'
)))
config
.
read
_file
(
open
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'telescope.ini'
)))
logging
.
basicConfig
(
level
=
logging
.
DEBUG
)
...
...
@@ -20,22 +19,25 @@ _telescope__num_instances = 0
__version__
=
"1.1.1"
class
telescope
():
def
__init__
(
self
,
setmode
=
None
,
consoleHost
=
None
):
'''
Initializes a telescope instance. The mode for writing can be
'J2000' or 'AZEL'.
'''
global
__num_instances
if
setmode
not
in
(
'J2000'
,
'AZEL'
,
None
):
raise
ValueError
(
"Mode must be None, 'J2000' or 'AZEL', not "
+
setmode
)
self
.
setmode
=
setmode
class
Telescope
:
def
__init__
(
self
,
setMode
=
None
,
consoleHost
=
None
):
"""
Initializes a telescope instance
:param setMode: The mode for writing. Can be 'J2000' or 'AZEL'
:param consoleHost: Address of the console. E.g. 'console' or 'consoledemo.dmz.camras.nl'
"""
global
_telescope__num_instances
if
setMode
not
in
(
'J2000'
,
'AZEL'
,
None
):
raise
ValueError
(
"Mode must be None, 'J2000' or 'AZEL', not "
+
setMode
)
self
.
setmode
=
setMode
if
consoleHost
is
None
:
consoleHost
=
config
.
get
(
'Console'
,
'HostName'
)
consoleHost
=
config
.
get
(
'Console'
,
'HostName'
)
if
consoleHost
==
'console'
:
if
socket
.
gethostname
()
==
"mercurius"
:
if
setMode
is
not
None
and
socket
.
gethostname
()
==
"mercurius"
:
logging
.
warning
(
"You are using the actual console, not a demo!"
)
else
:
raise
ValueError
(
"Talking to the actual console can only be done from mercurius"
)
...
...
@@ -49,22 +51,22 @@ class telescope():
self
.
speed_el
=
None
self
.
focusbox_pos
=
None
__num_instances
+=
1
_telescope
__num_instances
+=
1
if
__num_instances
!=
1
:
if
_telescope
__num_instances
!=
1
:
raise
RuntimeError
(
"Do not make more than one telescope instance."
)
self
.
_outsocket
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
if
self
.
setmode
==
'J2000'
:
try
:
self
.
_outsocket
.
connect
((
consoleHost
,
config
.
getint
(
'Console'
,
'Port_Write_J2000'
)))
config
.
getint
(
'Console'
,
'Port_Write_J2000'
)))
except
socket
.
gaierror
as
e
:
raise
IOError
(
"Could not connect to DT J2000 port: "
+
str
(
e
))
elif
self
.
setmode
==
'AZEL'
:
try
:
self
.
_outsocket
.
connect
((
consoleHost
,
config
.
getint
(
'Console'
,
'Port_Write_AzEl'
)))
config
.
getint
(
'Console'
,
'Port_Write_AzEl'
)))
except
socket
.
gaierror
as
e
:
raise
IOError
(
"Could not connect to DT AZEL port: "
+
str
(
e
))
...
...
@@ -73,38 +75,41 @@ class telescope():
self
.
_offsetsocket
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
try
:
self
.
_offsetsocket
.
connect
((
consoleHost
,
config
.
getint
(
'Console'
,
'Port_Write_Offset'
)))
config
.
getint
(
'Console'
,
'Port_Write_Offset'
)))
except
socket
.
gaierror
as
e
:
raise
IOError
(
"Could not connect to DT Offset port: "
+
str
(
e
))
self
.
_event_j2000
=
threading
.
Event
()
thread_read_j2000
=
threading
.
Thread
(
target
=
self
.
_readj2000
,
args
=
(
consoleHost
,
config
.
getint
(
'Console'
,
'Port_Read_J2000'
)))
consoleHost
,
config
.
getint
(
'Console'
,
'Port_Read_J2000'
)))
thread_read_j2000
.
daemon
=
True
thread_read_j2000
.
start
()
self
.
_event_traces
=
threading
.
Event
()
thread_read_traces
=
threading
.
Thread
(
target
=
self
.
_readtraces
,
args
=
(
consoleHost
,
config
.
getint
(
'Console'
,
'Port_Trace2Port'
)))
consoleHost
,
config
.
getint
(
'Console'
,
'Port_Trace2Port'
)))
thread_read_traces
.
daemon
=
True
thread_read_traces
.
start
()
def
_readj2000
(
self
,
consolehost
,
j2000_read_port
):
'''
Poll the socket with the j2000 info, store its values in class members.
'''
def
_readj2000
(
self
,
consoleHost
,
j2000_read_port
):
"""
Poll the socket with the J2000 info, store its values in class members
:param consoleHost: Hostname
:param j2000_read_port: Port with J200 info
:return: None
"""
try
:
self
.
_j2000socket
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
self
.
_j2000socket
.
connect
((
console
h
ost
,
j2000_read_port
))
self
.
_j2000socket
.
connect
((
console
H
ost
,
j2000_read_port
))
except
socket
.
error
:
raise
IOError
(
"Cannot connect to j2000 status server"
)
while
True
:
readable
,
writable
,
exceptional
=
select
.
select
(
[
self
.
_j2000socket
],
[],
[])
if
len
(
exceptional
)
>
0
:
[
self
.
_j2000socket
],
[],
[])
if
len
(
exceptional
)
>
0
:
raise
IOError
(
"Error with j2000 read socket"
)
msg
=
readable
[
0
].
recv
(
4096
).
decode
(
"UTF-8"
)
vals
=
msg
.
strip
().
split
()
...
...
@@ -119,6 +124,13 @@ class telescope():
self
.
_event_j2000
.
set
()
def
_readtraces
(
self
,
tracehost
,
traceport
):
"""
Poll the socket with the traces (a running 'trace2port' instance), store the trace values
in class members
:param tracehost: Hostname
:param traceport: Port at which trace2port is running
:return: None
"""
'''
Poll the socket with the traces, store their values in class members
'''
...
...
@@ -130,21 +142,27 @@ class telescope():
while
True
:
readable
,
writable
,
exceptional
=
select
.
select
(
[
self
.
_tracesocket
],
[],
[])
if
len
(
exceptional
)
>
0
:
[
self
.
_tracesocket
],
[],
[])
if
len
(
exceptional
)
>
0
:
raise
IOError
(
"Error with trace read socket"
)
msg
=
readable
[
0
].
recv
(
4096
).
decode
(
"UTF-8"
)
vals
=
msg
.
strip
().
split
()
self
.
az
=
(
float
(
vals
[
0
])
*
u
.
rad
).
to
(
u
.
deg
)
self
.
el
=
(
float
(
vals
[
1
])
*
u
.
rad
).
to
(
u
.
deg
)
self
.
dist_az
=
(
float
(
vals
[
2
])
*
u
.
rad
).
to
(
u
.
deg
)
self
.
dist_el
=
(
float
(
vals
[
3
])
*
u
.
rad
).
to
(
u
.
deg
)
self
.
az
=
(
float
(
vals
[
0
])
*
u
.
rad
).
to
(
u
.
deg
)
self
.
el
=
(
float
(
vals
[
1
])
*
u
.
rad
).
to
(
u
.
deg
)
self
.
dist_az
=
(
float
(
vals
[
2
])
*
u
.
rad
).
to
(
u
.
deg
)
self
.
dist_el
=
(
float
(
vals
[
3
])
*
u
.
rad
).
to
(
u
.
deg
)
self
.
speed_az
=
float
(
vals
[
4
])
self
.
speed_el
=
float
(
vals
[
5
])
self
.
focusbox_pos
=
float
(
vals
[
6
])
self
.
_event_traces
.
set
()
def
setRaDec
(
self
,
setpoint
):
"""
Set the J2000 setpoint of the telescope.
Only works if the telescope is in J2000 mode.
:param setpoint: New setpoint. An astropy SkyCoord or a tuple (ra, dec) in radians
:return: None
"""
'''
Set the J2000 setpoint of the telescope.
Only works if the setmode is 'J2000'.
...
...
@@ -155,22 +173,23 @@ class telescope():
raise
ValueError
(
"Cannot set Ra/Dec if mode is not J2000"
)
if
isinstance
(
setpoint
,
tuple
):
coord
=
SkyCoord
(
ra
=
setpoint
[
0
]
*
u
.
radian
,
dec
=
setpoint
[
1
]
*
u
.
radian
)
setpoint
=
SkyCoord
(
ra
=
setpoint
[
0
]
*
u
.
radian
,
dec
=
setpoint
[
1
]
*
u
.
radian
)
(
ra
,
dec
)
=
setpoint
.
to_string
(
'hmsdms'
).
split
()
(
ra
,
dec
)
=
setpoint
.
to_string
(
'hmsdms'
).
split
()
cmd
=
'{:s}
\t
{:s}
\n
'
.
format
(
ra
,
dec
.
strip
(
'+'
)).
encode
(
'UTF-8'
)
logging
.
info
(
'J2000 setpoint sent to DT: {}'
.
format
(
cmd
))
self
.
_outsocket
.
send
(
cmd
)
def
setAzEl
(
self
,
setpoint
):
'''
"""
Set the AzEl setpoint of the telescope.
Only works if the setmode is 'AZEL'
setpoint should be a tuple of degrees or of astropy Quantity
'''
:param setpoint: New setpoint. A tuple of floats (interpreted as degrees), or
a tuple of astropy Quantity
:return: None
"""
if
self
.
setmode
!=
'AZEL'
:
raise
ValueError
(
"Cannot set Az/El if mode is not AZEL"
)
...
...
@@ -185,11 +204,12 @@ class telescope():
self
.
_outsocket
.
send
(
cmd
)
def
setOffset
(
self
,
offset
):
'''
"""
Set the offset of the telescope in Az / El.
offset should be a tuple of degrees or of astropy Quantity
'''
:param offset: New setpoint. A tuple of floats (interpreted as radians), or
a tuple of astropy Quantity
:return: None
"""
if
self
.
setmode
is
None
:
raise
ValueError
(
"Cannot set offset if mode is None"
)
...
...
@@ -208,103 +228,109 @@ class telescope():
self
.
_offsetsocket
.
send
(
cmd
)
def
getFocusboxPosition
(
self
,
waitForUpdate
=
False
):
'''
Get the focusbox position.
If waitForUpdate=True, it waits for the
next signal from the socket
.
R
eturn
s an a
stropy quantity
'''
"""
Get the focusbox position.
:param waitForUpdate: wait for the
next signal from the socket
:r
eturn
: A
stropy quantity
with the focusbox position
"""
if
waitForUpdate
or
self
.
focusbox_pos
is
None
:
self
.
_event_traces
.
clear
()
self
.
_event_traces
.
wait
()
return
self
.
focusbox_pos
*
0.1
*
u
.
m
def
getAzEl
(
self
,
waitForUpdate
=
False
):
'''
"""
Get azimut and elevation. If waitForUpdate=True, it waits for the
next signal from the socket.
Returns a tuple (az, el) as astropy quantity
'''
"""
if
waitForUpdate
or
self
.
az
is
None
or
self
.
radec
is
None
:
self
.
_event_traces
.
clear
()
self
.
_event_traces
.
wait
()
return
(
self
.
az
,
self
.
el
)
def
getDistance
(
self
,
waitForUpdate
=
False
):
'''
"""
Get distance in azimut and elevation. If waitForUpdate=True, it waits
for the next signal from the socket.
Returns a tuple (dist_az, dist_el) as astropy quantity
'''
"""
if
waitForUpdate
or
self
.
dist_az
is
None
or
self
.
dist_el
is
None
:
self
.
_event_traces
.
clear
()
self
.
_event_traces
.
wait
()
return
(
self
.
dist_az
,
self
.
dist_el
)
def
getRaDec
(
self
,
waitForUpdate
=
False
):
'''
"""
Get current Ra/Dec. If waitForUpdate=True, it waits for the
next signal from the socket.
Returns an astropy SkyCoord
'''
"""
if
waitForUpdate
or
self
.
radec
is
None
:
self
.
_event_traces
.
clear
()
self
.
_event_traces
.
wait
()
return
self
.
radec
def
getSetpoint_RaDec
(
self
,
waitForUpdate
=
False
):
'''
"""
Get current Ra/Dec setpoint. If waitForUpdate=True, it waits for the
next signal from the socket.
Returns an astropy SkyCoord
'''
"""
if
waitForUpdate
or
self
.
radec
is
None
:
self
.
_event_traces
.
clear
()
self
.
_event_traces
.
wait
()
return
self
.
setpoint_radec
def
waitUntilThere
(
self
,
tolerance
=
0.01
*
u
.
deg
):
'''
def
waitUntilThere
(
self
,
tolerance
=
0.01
*
u
.
deg
):
"""
Wait until distance to the setpoint gets within tolerance
'''
"""
logging
.
info
(
"Waiting to reach setpoint"
)
distIsSmall
=
False
while
not
distIsSmall
:
diff
=
self
.
getDistance
(
waitForUpdate
=
True
)
distIsSmall
=
abs
(
self
.
dist_el
)
<
tolerance
and
abs
(
self
.
dist_az
)
<
tolerance
distIsSmall
=
abs
(
self
.
dist_el
)
<
tolerance
and
abs
(
self
.
dist_az
)
<
tolerance
def
waitUntilMoving
(
self
,
tolerance
=
0.01
*
u
.
deg
):
'''
def
waitUntilMoving
(
self
,
tolerance
=
0.01
*
u
.
deg
):
"""
Wait until the telescope reckognizes that it is not at its setpoint
'''
"""
logging
.
info
(
"Waiting to set setpoint"
)
distIsBig
=
False
while
not
distIsBig
:
dist
=
self
.
getDistance
(
waitForUpdate
=
True
)
distIsBig
=
dist
[
0
]
>
tolerance
or
dist
[
1
]
>
tolerance
distIsBig
=
dist
[
0
]
>
tolerance
or
dist
[
1
]
>
tolerance
def
getJ2000
(
self
):
'''
"""
Generates dicts with 'radec' and 'setpoint_radec',
containing radec and setpoint_radec, at whichever
speed the console is outputting them (probably once a second).
'''
"""
self
.
_event_traces
.
clear
()
while
True
:
self
.
_event_j2000
.
wait
()
self
.
_event_j2000
.
clear
()
yield
({
'radec'
:
self
.
radec
,
'setpoint_radec'
:
self
.
setpoint_radec
})
yield
({
'radec'
:
self
.
radec
,
'setpoint_radec'
:
self
.
setpoint_radec
})
def
getTraces
(
self
):
'''
"""
Generates a dict of all traces from trace2port at whichever
rate trace2port generates them (probably once a second).
'''
"""
self
.
_event_traces
.
clear
()
while
True
:
self
.
_event_traces
.
wait
()
self
.
_event_traces
.
clear
()
yield
({
'position_azel'
:
(
self
.
az
,
self
.
el
),
'distance'
:
(
self
.
dist_az
,
self
.
dist_el
),
'speed'
:
(
self
.
speed_az
,
self
.
speed_el
)})
yield
({
'position_azel'
:
(
self
.
az
,
self
.
el
),
'distance'
:
(
self
.
dist_az
,
self
.
dist_el
),
'speed'
:
(
self
.
speed_az
,
self
.
speed_el
)})
class
telescope
(
Telescope
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
Telescope
,
self
).
__init__
(
*
args
,
**
kwargs
)
logging
.
warning
(
"Please use the new class name Telescope (with capital T)"
)
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment