PyEphem: How to test if an object is above the horizon? - python-3.x

I am writing a Python script that gives basic data for all the planets, the Sun and the Moon. My first function divides the planets between those that are above the horizon, and those that are not risen yet:
planets = {
'mercury': ephem.Mercury(),
'venus': ephem.Venus(),
'mars': ephem.Mars(),
'jupiter': ephem.Jupiter(),
'saturn': ephem.Saturn(),
'uranus': ephem.Uranus(),
'neptune': ephem.Neptune()
}
def findVisiblePlanets(obs):
visiblePlanets = dict()
notVisiblePlanets = dict()
for obj in planets:
planets[obj].compute(obs)
if planets[obj].alt > 0:
visiblePlanets[obj] = planets[obj]
else:
notVisiblePlanets[obj] = planets[obj]
return (visiblePlanets, notVisiblePlanets)
This works alright, the tuple I receive from findVisiblePlanets corresponds corresponds to the actual sky for the given 'obs'.
But in another function, I need to test the altitude of each planet. If it's above 0, the script displays 'setting at xxx', and if it's under 0, the script displays 'rising at xxx'. Here is the code:
if bodies[obj].alt > 0:
print(' Sets at', setTime.strftime('%H:%M:%S'), deltaSet)
else:
print(' Rises at', riseTime.strftime('%H:%M:%S'), deltaRise)
So I'm using the exact same condition, except that this time it doesn't work. I am sure I have the correct object behind bodies[obj], as the script displays name, magnitude, distance, etc. But for some reason, the altitude (.alt) is always below 0, so the script only displays the rising time.
I tried print(bodies[obj].alt), and I receive a negative figure in the form of '-0:00:07.8' (example). I tried using int(bodies[obj].alt) for the comparison but this ends up being a 0. How can I test if the altitude is negative? Am I missing something obvious here?
Thanks for your help.

I thinkk I had a similar problem once. How I understand it pyephem forwards the time of your observer, when you call nextrising() or nextsetting() on a object. It somehow looks, at which timepoint the object is above/below the horizont for the first time. if you then call the bodie.alt it will always be this little bit below/above horizon.
You have to store your observer time somehow and set it again after calculating setting/rising times.

Related

Defining a function to find the unique palindromes in a given string

I'm kinda new to python.I'm trying to define a function when asked would give an output of only unique words which are palindromes in a string.
I used casefold() to make it case-insensitive and set() to print only uniques.
Here's my code:
def uniquePalindromes(string):
x=string.split()
for i in x:
k=[]
rev= ''.join(reversed(i))
if i.casefold() == rev.casefold():
k.append(i.casefold())
print(set(k))
else:
return
I've tried to run this line
print( uniquePalindromes('Hanah asked Sarah but Sarah refused') )
The expected output should be ['hanah','sarah'] but its returning only {'hanah'} as the output. Please help.
Your logic is sound, and your function is mostly doing what you want it to. Part of the issue is how you're returning things - all you're doing is printing the set of each individual word. For example, when I take your existing code and do this:
>>> print(uniquePalindromes('Hannah Hannah Alomomola Girafarig Yes Nah, Chansey Goldeen Need log'))
{'hannah'}
{'alomomola'}
{'girafarig'}
None
hannah, alomomola, and girafarig are the palindromes I would expect to see, but they're not given in the format I expect. For one, they're being printed, instead of returned, and for two, that's happening one-by-one.
And the function is returning None, and you're trying to print that. This is not what we want.
Here's a fixed version of your function:
def uniquePalindromes(string):
x=string.split()
k = [] # note how we put it *outside* the loop, so it persists across each iteration without being reset
for i in x:
rev= ''.join(reversed(i))
if i.casefold() == rev.casefold():
k.append(i.casefold())
# the print statement isn't what we want
# no need for an else statement - the loop will continue anyway
# now, once all elements have been visited, return the set of unique elements from k
return set(k)
now it returns roughly what you'd expect - a single set with multiple words, instead of printing multiple sets with one word each. Then, we can print that set.
>>> print(uniquePalindromes("Hannah asked Sarah but Sarah refused"))
{'hannah'}
>>> print(uniquePalindromes("Hannah and her friend Anna caught a Girafarig and named it hannaH"))
{'anna', 'hannah', 'girafarig', 'a'}
they are not gonna like me on here if I give you some tips. But try to divide the amount of characters (that aren't whitespace) into 2. If the amount on each side is not equivalent then you must be dealing with an odd amount of letters. That means that you should be able to traverse the palindrome going downwards from the middle and upwards from the middle, comparing those letters together and using the middle point as a "jump off" point. Hope this helps

How to process the data returned from a function (Python 3.7)

Background:
My question should be relatively easy, however I am not able to figure it out.
I have written a function regarding queueing theory and it will be used for ambulance service planning. For example, how many calls for service can I expect in a given time frame.
The function takes two parameters; a starting value of the number of ambulances in my system starting at 0 and ending at 100 ambulances. This will show the probability of zero calls for service, one call for service, three calls for service….up to 100 calls for service. Second parameter is an arrival rate number which is the past historical arrival rate in my system.
The function runs and prints out the result to my screen. I have checked the math and it appears to be correct.
This is Python 3.7 with the Anaconda distribution.
My question is this:
I would like to process this data even further but I don’t know how to capture it and do more math. For example, I would like to take this list and accumulate the probability values. With an arrival rate of five, there is a cumulative probability of 61.56% of at least five calls for service, etc.
A second example of how I would like to process this data is to format it as percentages and write out a text file
A third example would be to process the cumulative probabilities and exclude any values higher than the 99% cumulative value (because these vanish into extremely small numbers).
A fourth example would be to create a bar chart showing the probability of n calls for service.
These are some of the things I want to do with the queueing theory calculations. And there are a lot more. I am planning on writing a larger application. But I am stuck at this point. The function writes an output into my Python 3.7 console. How do I “capture” that output as an object or something and perform other processing on the data?
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import math
import csv
def probability_x(start_value = 0, arrival_rate = 0):
probability_arrivals = []
while start_value <= 100:
probability_arrivals = [start_value, math.pow(arrival_rate, start_value) * math.pow(math.e, -arrival_rate) / math.factorial(start_value)]
print(probability_arrivals)
start_value = start_value + 1
return probability_arrivals
#probability_x(arrival_rate = 5, x = 5)
#The code written above prints to the console, but my goal is to take the returned values and make other calculations.
#How do I 'capture' this data for further processing is where I need help (for example, bar plots, cumulative frequency, etc )
#failure. TypeError: writerows() argument must be iterable.
with open('ExpectedProbability.csv', 'w') as writeFile:
writer = csv.writer(writeFile)
for value in probability_x(arrival_rate = 5):
writer.writerows(value)
writeFile.close()
#Failure. Why does it return 2. Yes there are two columns but I was expecting 101 as the length because that is the end of my loop.
print(len(probability_x(arrival_rate = 5)))
The problem is, when you write
probability_arrivals = [start_value, math.pow(arrival_rate, start_value) * math.pow(math.e, -arrival_rate) / math.factorial(start_value)]
You're overwriting the previous contents of probability_arrivals. Everything that it held previously is lost.
Instead of using = to reassign probability_arrivals, you want to append another entry to the list:
probability_arrivals.append([start_value, math.pow(arrival_rate, start_value) * math.pow(math.e, -arrival_rate) / math.factorial(start_value)])
I'll also note, your while loop can be improved. You're basically just looping over start_value until it reaches a certain value. A for loop would be more appropriate here:
for s in range(start_value, 101): # The end value is exclusive, so it's 101 not 100
probability_arrivals = [s, math.pow(arrival_rate, s) * math.pow(math.e, -arrival_rate) / math.factorial(s)]
print(probability_arrivals)
Now you don't need to manually worry about incrementing the counter.

How to set the r_bar part of tqdm

I use tqdm to print a progress bar for a long running optimization process with hyperopt.
The process calls a function say 500 times and each call will take around 10 to 20 minutes, so I started to make the progress display a bit more fine granular and added some tqdm.update-statements in the loop, advancing the progress bar fraction-wise to avoid having two nested progress bars while still beeing able to immediately see how many function calls have been performed so far.
Now the ugly result looks like this:
15%|███▌ | 73.69999999999993/500 [7:40:31<102:54:08, 868.98s/it, evaluating fold 2 of 2 folds...]Iteration 1, loss = 2.50358388
You can see above, it is the 73th call of the function and this 73th function call is about 70% finished. In fact I just estimated the number of substeps m in the function (which might vary from call to call) and used the fraction 1/m to update the progress bar. Then after the function call I just synchronize the progress bar back to a full integer to avoid adding rounding errors.
Of course accuracy is not an issue at all here. But I would like to display 73.70 rather than 73.69999999999993.
I already tried to round my update value to two decimal places, which doesn't fix the problem, because of precision issues in float, if a number is not exactly representable by a float, then it gets ugly-long again.
According to the documentation of tqdm this part is hidden in the in the part r_bar of the whole format string, but I couldn't find a way to set it. Can you help me with this?
According to the docs r_bar defaults to:
r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
Here is my code:
with tqdm(iterable=None, initial=num_trials, maxinterval=maxinterval, total=max_evals, ascii=False, disable=show_progressbar is False) as progress_bar:
def fn_to_minimize(*args, **kwargs):
return fn(*args, **kwargs, _progress_bar=progress_bar)
for num_trials in range(num_trials, max_evals):
progress_bar.n=float(num_trials)
progress_bar.refresh()
best = fmin(**kwargs, fn=fn_to_minimize, trials=trials, max_evals=num_trials+1)
# do some other stuff here
In the called function (one of the entries in kwargs btw) I update the progress bar just like this:
_progress_bar.update(round(update_value, 2))
For rounding issues in tqdm, you can directly edit the formatting in the r_bar as one of the parameters in the bar_format. For example:
from tqdm import trange
for i in trange(int(7e7), bar_format = "{desc}: {percentage:.3f}%|{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}"):
pass
shows:
For 2 decimal places, you can simply edit the {n_fmt} to be {n:.2f} . You can also edit other parameters such as {desc} or add in additional decimal places to the percentage.
from tqdm import trange
for i in trange(int(7e7), bar_format = "{desc}: {percentage:.10f}%|{bar}| {n:.2f}/{total_fmt} [{elapsed}<{remaining}"):
pass
shows:
Upon looking through the source code of tqdm, n_fmt is actually pointing to str(n), hence passing in the formatted version of n can bypass its intrinsic formatting.
if unit_scale:
n_fmt = format_sizeof(n, divisor=unit_divisor)
total_fmt = format_sizeof(total, divisor=unit_divisor) \
if total is not None else '?'
else:
n_fmt = str(n)
total_fmt = str(total) if total is not None else '?'
try:
postfix = ', ' + postfix if postfix else ''
except TypeError:
pass

Program ignores all the numbers after the 1st one

Why the program takes just the first number in the list and ignores others, making an empty list.
This happens in every function with for loop.
cars=[23.11,1531,'volvo','BMW']
def price(CAR):
num=[]
strings=[]
for i in CAR:
if isinstance(i,float)or isinstance(i,int):
num.append(i)
elif isinstance(i,str):
strings.append(i)
else:
pass
return num,strings
print(price(cars))
([23.11], [])
The only reason I can think of is, your return statement is aligned with your for loop, so it exists after the first iteration. (Though it looks aligned correctly right now, maybe the editor corrected it instinctively.)

how to predict with gaussianhmm sklearn

I'm trying to predict stock prices using sklearn. I'm new to prediction. I tried the example from sklearn for stock prediction with gaussian hmm. But predict gives states sequence which overlay on the price and it also takes points from given input close price. My question is how to generate next 10 prices?
You will always use the last state to predict the next state, so let's add 10 days worth of inputs by changing the end date to the 23rd:
date2 = datetime.date(2012, 1, 23)
You can double check the rest of the code to make sure I am not actually using future data for the prediction. The rest of these lines can be added to the bottom of the file. First we want to find out what the expected return is for a given state. The model.means_ array has returns, both those were the returns that got us to this state, not the future returns which is what you want. To get the future returns, we consider the probability of going to any one of the 5 states, and what the return of those states is. We get the probability of going to any particular state from the model.transmat_ matrix, the for the return of each state we use the model.means_ values. We take the dot product to get the expected return for a particular state. Then we remove the volume data (you can leave it in if you want, but you seemed to be most interested in future prices).
expected_returns_and_volumes = np.dot(model.transmat_, model.means_)
returns_and_volumes_columnwise = zip(*expected_returns_and_volumes)
returns = returns_and_volumes_columnwise[0]
If you print the value for returns[0], you'll see the expected return in dollars for state 0, returns[1] for state 1 etc. Now, given a day and a state, we want to predict the price for tomorrow. You said 10 days so let's use that for lastN.
predicted_prices = []
lastN = 10
for idx in xrange(lastN):
state = hidden_states[-lastN+idx]
current_price = quotes[-lastN+idx][2]
current_date = datetime.date.fromordinal(dates[-lastN+idx])
predicted_date = current_date + datetime.timedelta(days=1)
predicted_prices.append((predicted_date, current_price + returns[state]))
print(predicted_prices)
If you were running this in "production" you would set date2 to the last date you have and then lastN would be 1. Note that I don't take into account weekends for the predicted_date.
This is a fun exercise but you probably wouldn't run this in production, hence the quotes. First, the time series is the raw price; this should really be percentage returns or log returns. Plus there is no justification for picking 5 states for the HMM, or that a HMM is even good for this kinda problem, which I doubt. They probably just picked it as an example. I think the other sklearn example using PCA is much more interesting.

Resources