The original announcement is in Solar diagrams.
This uses Pysolar to calculate the altitude and azimuth angles of the sun at a given coordinate on Earth (latitude and longitude) over the entire year, and then FreeCAD draws the diagram.
However, at some point the sun diagram stopped working due to different reasons:
- Pysolar changed name and was incorrectly imported in the code
- Pysolar was updated to work only with Python 3, so it didn't work with FreeCAD versions compiled against Python 2
This code tests whether the Pysolar module is available in Python 3; it uses subprocess.call() to externally call the python3 interpreter. If Python 3 is available it uses that, otherwise it tries to import Pysolar assuming Python 2. If Pysolar is not available at all, it just returns, and doesn't create anything.
Code: Select all
def makeSolarDiagram(longitude,latitude,scale=1,complete=False):
from subprocess import call
py3_failed = call(["python3", "-c", "import Pysolar"])
if py3_failed:
try:
import Pysolar
except:
print("Pysolar is not installed. Unable to generate solar diagrams")
return None
else:
from subprocess import check_output
Code: Select all
for h in range(24):
if not py3_failed:
dt = "datetime.datetime(%s, %s, %s, %s)" % (year, d[0], d[1], h)
alt_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_altitude_fast(%s, %s, %s))'" % (latitude, longitude, dt)
alt = math.radians(float(check_output(alt_call, shell=True).strip()))
az_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_azimuth(%s, %s, %s))'" % (latitude, longitude, dt)
az = float(re.search('.+$', check_output(az_call, shell=True)).group(0))
else:
dt = datetime.datetime(year,d[0],d[1],h)
alt = math.radians(Pysolar.solar.GetAltitudeFast(latitude,longitude,dt))
az = Pysolar.solar.GetAzimuth(latitude,longitude,dt)
The proposed changes are as follows.
Just try to import Pysolar, which is now named all lowercase, pysolar.
Code: Select all
def makeSolarDiagram(longitude,latitude,scale=1,complete=False):
try:
import pysolar
except:
print("Pysolar is not installed. Unable to generate solar diagrams")
return None
Code: Select all
for h in range(24):
dt = datetime.datetime(year, d[0], d[1], h, tzinfo=datetime.timezone.utc)
alt = math.radians(pysolar.solar.get_altitude_fast(latitude, longitude, dt))
az = pysolar.solar.get_azimuth(latitude, longitude, dt)
They were tested with this version
Code: Select all
OS: Ubuntu 18.04.2 LTS
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.18.1.
Build type: Release
Python version: 3.6.7
Qt version: 5.9.5
Coin version: 4.0.0a
OCC version: 7.3.0
Locale: English/UnitedStates (en_US)
Further information.
The Pysolar developer decided to drop support for Python 2, and has made the software only compatible with Python 3. This happened in the transition from Pysolar 0.6 to 0.7. Also, the functions were renamed to comply with PEP8 (lowercase_with_underscores instead of camelCase).
In Debian/Ubuntu systems Pysolar can be installed from the repositories, but again, in recent times it's only available for Python 3.
Code: Select all
sudo apt install python3-pysolar
Code: Select all
solartime.py:107: UserWarning: I don't know about leap seconds after 2016
-----------------------
If Arch wishes to keep supporting Pysolar with Python 2 then this could be implemented like the original code above, that is, test for the presence of the python2 interpreter, import Pysolar 0.6, and call the older functions. It should necessarily import version 0.6 as that is the last version supported by Python 2.
Code: Select all
for h in range(24):
if py3_available:
dt = datetime.datetime(year, d[0], d[1], h, tzinfo=datetime.timezone.utc)
alt = math.radians(pysolar.solar.get_altitude_fast(latitude, longitude, dt))
az = pysolar.solar.get_azimuth(latitude, longitude, dt)
elif py2_available:
dt = "datetime.datetime(%s, %s, %s, %s)" % (year, d[0], d[1], h)
alt_call = "python2 -c 'import datetime,Pysolar; print (Pysolar.solar.GetAltitudeFast(%s, %s, %s))'" % (latitude, longitude, dt)
alt = math.radians(float(check_output(alt_call, shell=True).strip()))
az_call = "python2 -c 'import datetime,Pysolar; print (Pysolar.solar.GetAzimuth(%s, %s, %s))'" % (latitude, longitude, dt)
az = float(re.search('.+$', check_output(az_call, shell=True)).group(0))