Я полагаю, проблема в том, что вы вручную конвертируете из ephem.Angle()
(который является объектом ra
, azi
и т. Д.) В float
.
EDIT
В частности, проблема возникает из-за того, что в вашей функции cSTI()
, когда значение отрицательное, вы должны вычитать (а не добавлять) разные значения.
Исправленная реализация будет выглядеть следующим образом:
import math
def cSTI(number):
degrees = int(number[0])
minutes = int(number[1])
seconds = float(number[2])
full = degrees + \
math.copysign((minutes / 60), degrees) + \
math.copysign((seconds / 60 / 60), degrees)
return round(full, 2)
Обратите внимание, что это своего рода минимальная модификация вашего кода, чтобы заставить его работать.Я бы предложил вам написать несколько документов о том, как написать лучший код, начиная с PEP8 .Кроме того, вам следует избегать магических чисел , подобных диким 60
в вашем коде.
Если бы я делал это вручную, я бы также избегал использования ненужных регулярных выражений и фактически начинал быиз ephem.Angle()
объекта, подобного:
import math
MIN_IN_DEG = SEC_IN_MIN = 60
def ephem_angle_to_float(angle):
degrees, minutes, seconds = [float(s) for s in str(angle).split(':')]
value = abs(degrees) + \
minutes / MIN_IN_DEG + \
seconds / SEC_IN_MIN / MIN_IN_DEG
return math.copysign(value, degrees)
, и это может быть вызвано непосредственно к planet.ra
или planet.dec
в вашем коде.
Но я бы не стал делать это вручную.См. Ниже.
Но хорошая новость заключается в том, что нет необходимости вручную вычислять это самостоятельно, вы можете просто привести его к float
для значения в радианах, как указано в официальная документация .
Следующий код является вашей отработанной версией, которая создает табличные данные в виде списка списков (которые можно легко преобразовать в CSV с помощью csv
из стандартной библиотеки Python).Был сделан ряд модификаций:
- небесные тела и массы теперь более явны
- объекты
ephem
создаются динамически - постоянная G теперьвзято из
scipy.constants
(которое извлекается из последних CODATA) - метки и данные создаются динамически
- по возможности избегалась явная индексация
- даты начала и окончаниябыли несколько перевернуты, поскольку это не имеет значения для проблемы
Обратите внимание, что здесь не выполняется преобразование, поскольку это может привести к потере информации.
Вот код:
import numpy as np
import scipy as sp
import ephem
import scipy.constants
import datetime
celestial_masses = {
'sun': 1.989e30,
'mercury': 0.330e24,
'venus': 4.870e24,
'earth': 5.970e24,
'moon': 0.073e24,
'mars': 0.642e24,
'jupiter': 1898e24,
'saturn': 568e24,
'uranus': 86.8e24,
'neptune': 102e24,
'pluto': 0.0146e24, }
celestials = {
name: (eval('ephem.{}()'.format(name.title())), mass)
for name, mass in celestial_masses.items() if name != 'earth'}
gg = sp.constants.gravitational_constant
observer = ephem.Observer()
# Revere, Massachusetts, USA
observer.lon = '-42.4084'
observer.lat = '71.0120'
start_datetime = datetime.datetime(2018, 9, 1, 12, 0, 0)
end_datetime = datetime.datetime(2018, 11, 30, 12, 0, 0)
values = 'ra', 'dec', 'azi', 'gforce'
labels = ('date',) + tuple(
'{}({})'.format(name, value)
for name in celestials.keys()
for value in values)
data = []
observer.date = start_datetime
delta_datetime = datetime.timedelta(minutes=30)
while (observer.date.datetime() < end_datetime):
row = [observer.date]
for name, (body, mass) in celestials.items():
body.compute(observer)
row.extend([
body.ra, body.dec, body.az,
gg * ((mass * celestial_masses['earth']) / (body.earth_distance ** 2))])
data.append(row)
observer.date = observer.date.datetime() + delta_datetime
Для преобразования в CSV (со значениями с плавающей запятой для ra
, dec
, az
и gforce
) это можно сделать следующим образом:
import csv
filepath = 'celestial_bodies_revere_MA.csv'
with open(filepath, 'w') as file_obj:
csv_obj = csv.writer(file_obj)
csv_obj.writerow(labels)
for row in data:
# : use default string conversion
# csv_obj.writerow(row)
# : a possible conversion to float for all but the `date`
csv_obj.writerow([
float(x) if i != labels.index('date') else x
for i, x in enumerate(row)])
Дополнительно,Вот некоторый код для графиков, показывающий, что проблема с отрицательными значениями исчезла:
import matplotlib as mpl
import matplotlib.pyplot as plt
x = [row[labels.index('date')].datetime() for row in data]
fig, axs = plt.subplots(4, 1, figsize=(16, 26))
for i, value in enumerate(values):
pos = i
for name in celestials.keys():
y = [row[labels.index('{}({})'.format(name, value))] for row in data]
axs[pos].plot(x, y, label=name)
axs[pos].set_title(value)
axs[pos].legend(loc='center left', bbox_to_anchor=(1, 0.5))
fig.tight_layout()
, что приводит к: