Cannot print alt and az using pyephem in function - python

I'm working on building a simple python program for a class which will run on a Raspberry Pi and an Arduino to direct a telescope. I had started to learn python some time ago, and I'm having trouble getting my functions to work properly. Right now, I have this:
import ephem
def const(p, d): # find the constellation #
def loc():
sbend = ephem.Observer()
sbend.lat = '41.67'
sbend.lon = '86.26'
p = getattr(ephem, p)
p.compute(sbend)
print p.alt, p.az
o = getattr(ephem, p)
print ephem.constellation(o(d))
return loc()
const(raw_input('Planet: '), raw_input('yyyy/mm/dd: '))
From what I remember, a function inside another can call a variable from the parent. Can it also work the other way round like I have at the end? I'd like to be able to print the constellation (which is working) as well as the alt and az of the planet based on the hardcoded location. For some reason, it isn't calculating the altitude and azimuth though. Thoughts?
EDIT
I added return loc() on line 14.
I was doing more reading and some other threads said that to get to an inner function, it needs to be returned at the end of the parent. But, it's still not working for me.

I am not clear on why you have one function inside of another, so I might be missing part of the problem that you are trying to solve; but if I wanted to determine in what constellation a planet lies, where the planet's name and the date are provided as inputs, then I would simply perform those steps all in a row, without any complicated functions-inside-of-functions:
import ephem
def const(planet_name, date_string):
planet_class = getattr(ephem, planet_name)
planet = planet_class()
south_bend = ephem.Observer()
south_bend.lat = '41.67'
south_bend.lon = '-86.26' # west is negative
south_bend.date = date_string
planet.compute(south_bend)
return ephem.constellation((planet.ra, planet.dec))
print const(raw_input('Planet: '), raw_input('yyyy/mm/dd: '))

Taking #Brandon's example, here is my final code:
import ephem
def const(planet_name, date_string):
planet_class = getattr(ephem, planet_name)
planet = planet_class()
south_bend = ephem.Observer()
south_bend.lat = '41.67'
south_bend.lon = '-86.26'
south_bend.date = date_string
planet.compute(south_bend)
print ephem.constellation((planet.ra, planet.dec))
return planet.alt, planet.az
print const(raw_input('Planet: '), raw_input('yyyy/mm/dd: '))
I realized after looking at it that he was using planet.ra and planet.dec to locate the background constellation, not to print it's coordinates in the sky. All I did was add the return call at the end to print the altitude and azimuth data.

Related

How to write a python script in Maya with a condition logic

I’m starting as a programmer and currently working on a project but got stuck + have a bit of a brain fart(sorry).
I need to write a tool that will:
1 - set character rig by selecting character in the scene and set script to remember selection.
2 - evaluate whether selected character rig has a namespace or not (depending on that the next step takes different root)
if there is a namespace:
3 - find control in the character rig [namespace] + [side L\R] + [Ctrl]
4 - select target loc and snap one to another then bake animation
if there is no namespace:
3 - find control in the character rig [side L\R] + [Ctrl]
4 - select target loc and snap one to another then bake animation
I wrote parts of the script but don’t know how to put it together because I don’t know how to word this condition in the script.
Can anyone help me to put my brain back in order?
CH = pm.ls(sl=True, fl=True)
for c in CH:
if pm.referenceQuery(c, isNodeReferenced=True):
nameSpace = c.split(':')[0] + ':'
nameS.append(nameSpace)
name = nameSpace + 'L' + '_Weapon_ctrl'
print name
else:
name = 'L' + '_Weapon_ctrl'
print name
def bakeToObj():
Target = pm.ls(sl=True, fl=True)[0]
pm.cutKey(Weapon)
par = pm.parentConstraint([Target] + [Weapon], mo=False)
startTime = pm.playbackOptions(query=True, minTime=True)
endTime = pm.playbackOptions(query=True, maxTime=True)
pm.bakeResults(Weapon, simulation=True, t=(startTime, endTime))
pm.showHidden(above=True)
pm.delete(par)
return bakeToObj
I recommend to continue where you started. The list ist a very good start. Now you can create a script with all functions you need for the list of tasks and one function to call them all, e.g.:
def getSelectedCharacterRig():
sel = pm.ls(sl=True, fl=True)
return sel
def getCtrlName(rig):
....
return ctrlName
def findCtrl(ctrlName):
...
return ctrl
def selectTargetLoc(ctrl):
...
def bake(someObject):
return bakedObject
def doIt():
selection = getSelectedCharacterRig()
ctrlName = getCtrlName(selection)
...
This way you can see what you need an how to do it. And you will see if a function is not needed at all.

Stuck in loop help - Python

The second 'if' statement midway through this code is using an 'or' between two conditions. This is causing the issue I just don't know how to get around it. The code is going through a data file and turning on the given relay number at a specific time, I need it to only do this once per given relay. If I use an 'and' between the conditions, it will only turn on the first relay that matches the current time and wait for the next hour and turn on the next given relay.
Could someone suggest something to fix this issue, thank you!
def schedule():
metadata, sched = dbx.files_download(path=RELAYSCHEDULE)
if not sched.content:
pass # If file is empty then exit routine
else:
relaySchedule = str(sched.content)
commaNum = relaySchedule.count(',')
data1 = relaySchedule.split(',')
for i in range(commaNum):
data2 = data1[i].split('-')
Time1 = data2[1]
currentRN = data2[0]
currentDT = datetime.datetime.now()
currentHR = currentDT.hour
global RN
global T
if str(currentHR) == str(Time1):
if T != currentHR or RN != currentRN:
relaynum = int(data2[0])
relaytime = int(data2[2])
T = currentHR
RN = currentRN
k = threading.Thread(target=SendToRelay(relaynum, relaytime)).start()
else:
print("Pass")
Desired Inputs:
sched.content = '1-19-10,3-9-20,4-9-10,'
T = ' '
RN = ' '
T and RN are global variables because the loop is running indefinitely, they're there to let the loop know whether the specific Time(T) and Relay Number(RN) have already been used.
Desired Outputs:
If the time is 9 AM then,
T = 9
RN should be whatever the given relay number is so RN = 3, but not sure this is the right thing to use.
Sorry if this is confusing. I basically need the program to read a set of scheduled times for specific relays to turn on, I need it to read the current time and if it matches the time in the schedule it will then check which relay is within that time and turn it on for however long. Once it has completed that, I need it to go over that same set of data in case there is another relay within the same time that also needs to turn on, the issue is that if I don't use T and RN variables to check whether a previous relay has been set, it will read the file and turn on the same relay over and over.
Try printing all used variables, check if everything is, what you think it is. On top of that, sometimes whietespaces characters causes problem with comparison.
I fixed it. For anyone wondering this is the new working code:
def schedule():
metadata, sched = dbx.files_download(path=RELAYSCHEDULE)
if not sched.content:
pass # If file is empty then exit routine
else:
relaySchedule = str(sched.content)
commaNum = relaySchedule.count(',')
data1 = relaySchedule.split(',')
for i in range(commaNum):
data2 = data1[i].split('-')
TimeSched = data2[1]
relaySched = data2[0]
currentDT = datetime.datetime.now()
currentHR = currentDT.hour
global RN
global T
if str(currentHR) == str(TimeSched):
if str(T) != str(currentHR):
RN = ''
T = currentHR
if str(relaySched) not in str(RN):
relaynum = int(data2[0])
relaytime = int(data2[2])
k = threading.Thread(target=SendToRelay(relaynum, relaytime)).start()
RN = str(RN) + str(relaySched)

Shortening an if, elif, elif else clause

I am making a program that checks when the next train leaves. For that, it takes the departure times from a website and stores them in arrays(times_luz and times_hitz).
However, the API sometimes doesn't have any Information, so there's no data in the array which, later in the code, leads to an error, Therefore I thought this would be a good Idea:
if times_hitz and times_luz:
Code to be executed if both contain values
elif times_luz:
Code to be executed if only times_luz contains values
elif times_hitz:
Code to be executed if only times_hitz contains values
else
print("No content available")
sys.exit()
This would technically work, but the code is currently about 30 lines long so I would have to Copy & Paste that Code 2 times with only slight changes. This would lead to about 80 lines of code and would look pretty ugly. Is there any better way of doing this?
Edit:
I made a huge mistake in guessing the size of my file, it's actually 103 lines long, including comments. Therefore, I decided to upload it to google drive:
https://drive.google.com/open?id=1F5FIuAy_g7sC_2wTprqg3EF_m_JXEreL
The error that occurs when there's no data in the array is on line 44 and 48 because the 1st item in the Array times_luz/hitz doesn't exist and can therefore not be saved to a variable. This means that I have to execute some code that only checks the _luz trains if there's nothing in times_hitz and the other way around. If both contain data, I want to execute the code I have on google drive and if neither contains data, it should print an error message.
The endings _luz and _hitz stand for Lucerne and Hitzkirch, the two ways a train can go at my station
This code basically takes times from a Train API and stores them in 3 different variables. It then checks the 3 times and stores the one that will depart next in a variable. It does this for _luz and _hitz. In the end, it checks which train(_luz or _hitz) departs earlier and prints the difference between datetime.now and the train departure time
Sorry if my explanation is unclear, feel free to ask more questions in the comments
There is some massive duplication in your code. Basically, the entire code for getting the next train is the same for the two destination (and any other destinations you might add later) and should be moved to a function.
def get_next_train(params):
res =requests.get(base, params=params)
parsed_json = res.json()
#Zeiten aus parsed_json extrahieren
time_strings = [d["from"]["prognosis"]["departure"]
for d in parsed_json["connections"]]
#String, um Zeiten in time_strings nach ISO 8601 zu parsen
iso_format = "%Y-%m-%dT%H:%M:%S%z"
# Time Strings zu datetime Objekten konvertieren
times = [datetime.strptime(ts, iso_format)
for ts in time_strings if ts is not None]
# Checken, ob times leer sind
if not times:
return None # CHANGE: return None if no times found
#Zeitzone der ersten zeit in Times speichern
tz = times[0].tzinfo
#jetztige Zeit mit Zeitzone tz, Mikrosekunden löschen
nowtime = datetime.now(tz).replace(microsecond=0)
# Checken, ob Time_1 noch in der Zukunft ist. Wenn ja, diese Zeit als Time_luz speichern
time = min(t for t in times[0:3] if t > nowtime) # CHANGE: use min
return time, time - nowtime
Then, you can get the results for the two destinations, and get the min after filtering results that are None, then just check whether that min is None (the default).
res_luz = get_next_train(params_luz)
res_hitz = get_next_train(params_hitz)
res = min(filter(None, (res_luz, res_hitz)), default=None)
if res is not None:
time, diff = res
print ("Next train", time, ", in", str(diff))
else:
print("Service nicht verfügbar")
Update: It seems like late in the evening, there might be no train departing after nowtime, causing the min to raise an exception. You can fix this by providing another default like below and returning None in this case, too.
time = min((t for t in times if t > nowtime), default=None)
return (time, time - nowtime) if time is not None else None
Update: If you want to know the destination of the next train (makes sense...) you can get it from the parameters and return it alongside the time and diff.
return time, time - nowtime, params["to"]
then unpack and print it:
if res is not None:
time, diff, dest = res
print ("Next train to %s at %s (in %s)" % (dest, time, diff))
you can instead make a definition in Python instead, so you define it once. And where ever you need to use this definition again, you can simply call it. You can also make it a class once this function gets more complicated.
Your code will be this instead:
def train_time(times_hitz, time_luz):
if times_hitz and times_luz:
Code to be executed if both contain values
elif times_luz:
Code to be executed if only times_luz contains values
elif times_hitz:
Code to be executed if only times_hitz contains values
else:
print("No content available")
sys.exit()
return leave
Where the "leave" will be from your executed code to determine when the next train leaves. And whenever you need to evaluate if the train is leaving, simply do:
leave = train_time(times_hitz, time_luz)

Python: Printing data only when number enters or leaves interval

Currently I'm making a script that, given a set of celestial coordinates, will tell you on the next days when that point will be visible for a specific telescope. The criteria is simple, in the Horizontal Coordinate system, altitude of the object must be between 30 and 65 degrees(Variable "crit" here represents that, but in radians).
So I have a set of parameters for the telescope called "Ant" and then, using Pyephem:
#imported ephem as ep
obj= ep.FixedBody()
obj._ra= E.ra
obj._dec= E.dec
obj._epoch = E.epoch
Ant.date = ep.now()
for d in range(days):
for i in range(24):
for j in range (60):
Ant.date += ep.minute
obj.compute(Ant)
crit= float(obj.alt)
if crit>=0.523599 and crit <=1.13446:
print "Visible at %s" %Ant.date
Which results in printing a lot of "Visible at 2016/7/11 19:41:21", 1 for every minute.
I Just want it to print something like "Enters visibility at 2016/7/11 19:41:21, leaves at 2016/7/11 23:41:00", for example.
Any Ideas will be appreciated.
Disclaimer: Sorry, not a native english speaker.
You need to keep track of whether it is already in range. So, for instance, at the beginning you'd initialize it:
is_visible = False
and your if statement might look like:
if crit>=0.523599 and crit <=1.13446:
if not is_visible:
print "Visible at %s" %Ant.date
is_visible = True
else:
if is_visible:
print "No longer visible at %s" % Ant.date
is_visible = False

Need assistance in modifying the python script to return wind direction in degrees

I am new to scripting and have only worked on arcpy modules specifically. I am currently using the scripts to get the wind details from "http://weather.noaa.gov/pub/data/observations/metar/stations". I need to integrate the wind direction in the web application and need assistance in modify the script to return only wind direction in degrees, Here is the link that I have downloaded the scripts from "http://pypi.python.org/pypi/metar/"
I have tried making the changes to Metar.py by adding a function to return direction only
def windDirection(self):
"""
Return a textual description of the wind conditions.
Units may be specified as "MPS", "KT", "KMH", or "MPH".
"""
if self.wind_speed == None:
return "missing"
elif self.wind_speed.value() == 0.0:
text = "calm"
else:
wind_speed = self.wind_speed.string(units)
text = "%s"(self.wind_dir.directVal)
return text
Also added a function to Datatypes.py"
def directVal( self ):
if not self._compass:
degrees = 22.5 * round(self._degrees/22.5)
if degrees == 360.0:
self._directVal = "N"
else:
for name, d in direction.compass_dirs.iteritems():
if d == degrees:
self._directVal = name
break
return self._directVal
I am not sure how to get this value returned as a separate text strong other than report. Please assist.
An alternative approach to METAR data (if you are in the US) is to connect to the station's NOAA observation XML data. While that is a bit lengthy to wade through, you can get a simple answer by using my PARFAIT API. To get back the current wind speed at LAX airport you'd use the Current Weather API: http://parfait.snarkybox.com/current.php?icao=klax&datum=current_observation,wind_mph
Full instructions are available on the API website: parfait dot snarkybox dot com.

Categories