def scale_planets(cls, scale_data: dict = None, do_moons: bool = True, debug: bool = False): """ Scales all defined planets to scales specified by scale_data Parameters ---------- scale_data: dict A dictionary do_moons: bool scale moons aroundPlanet moon_scales: dict provide a dictionary of args for the Moon.scale_moon() function debug (bool): enables debug messages """ scale_data = cls._default_scale_data if scale_data == None else utilz.merge_attributes( cls._default_scale_data, scale_data) [ i.scale_planet(scale_data=scale_data, debug=debug) for i in cls._instances ] if do_moons: [ i.scale_moon(scale_data=scale_data, debug=debug) for i in Moon._instances ]
def scale_distance(self, scale_data: dict = None, debug: bool = False) -> Planet: """ Returns a planet object with scaled distance values (semimajorAxis, semiminorAxis) standard scaling is performed by the function f(x) = x/(10**scaleExponent) Parameters ---------- scale_data: dict dictionary of overrides for default scale_data debug: bool output informational messages (default: False) """ scale_data = self.default_scale_data if scale_data == None else utilz.merge_attributes( self.default_scale_data, scale_data) print( f"INFO: {self.englishName} raw values [semimajorAxis -> {self.semimajorAxis}] [semiminorAxis -> ({self.semiminorAxis}]" ) if debug else None self.scaleDistExp = scale_data['planet']['scale_dist'] self.semimajorAxis = float(self.semimajorAxis / (10**self.scaleDistExp)) self.semiminorAxis = float(self.semiminorAxis / (10**self.scaleDistExp)) print( f"INFO: {self.englishName} scaled with [values/(10**{self.scaleDistExp})] [semimajorAxis -> {self.semimajorAxis}] [semiminorAxis -> {self.semiminorAxis}]" ) if debug else None return self
def scale_mass(self, scale_data: dict = None, debug: bool = False) -> Planet: """ Returns a planet object with scaled calculated mass value (massRawKG) standard scaling is performed by the function f(x) = x/(10**scaleExponent) Parameters ---------- scale_data: dict (dictionary of overrides for default scale_data) debug: bool output informational messages (default: False) """ scale_data = self.default_scale_data if scale_data == None else utilz.merge_attributes( self.default_scale_data, scale_data) print(f"INFO: {self.englishName} raw values [mass -> {self.massRawKG}]" ) if debug else None self.scaleMassExp = scale_data['planet']['scale_mass'] self.massExponent = self.massExponent - (self.scaleMassExp) self.massRawKG = float( f"{float(self.massValue*(10**self.scaleMassExp)):f}") print( f"INFO: {self.englishName} scaled with [values/(10**{self.scaleMassExp})] [mass ->{self.massRawKG}]" ) if debug else None return self
def scale_planet(self, scale_data: dict = None, do_moons: bool = False, debug: bool = False) -> Planet: """ Returns a planet object with scaled distance, size, calculated mass & volume values (equaRadius, meanRadius, massRawKG, volumeRawKG, semimajorAxis, semiminorAxis) standard scaling is performed by the function f(x) = x/(10**scaleExponent) Parameters ---------- scale_data: dict (dictionary of overrides for default scale_data) output informational messages (default: False) """ scale_data = self.default_scale_data if scale_data == None else utilz.merge_attributes( self.default_scale_data, scale_data) self.meanRadius = self.meanRadius self.equaRadius = self.equaRadius self.englishName = self.englishName print( f"INFO: {self.englishName} raw values [meanRadius -> {self.meanRadius}] [equaRadius -> {self.equaRadius}] [semimajorAxis -> {self.semimajorAxis}] [semiminorAxis -> {self.semiminorAxis}] [volValueRawKG -> {self.volumeRawKG}] [massRawKG -> {self.massRawKG}]" ) if debug else None self.scaleDistExp = scale_data['planet']['scale_dist'] self.scaleMassExp = scale_data['planet']['scale_mass'] self.scaleSizeExp = scale_data['planet']['scale_size'] self.scaleVolExp = scale_data['planet']['scale_vol'] self.semimajorAxis = self.semimajorAxis / (10**self.scaleDistExp) self.semiminorAxis = self.semiminorAxis / (10**self.scaleDistExp) self.volExponent = self.volExponent - (self.scaleVolExp) self.massExponent = self.massExponent - (self.scaleMassExp) self.massRawKG = float( f"{float(self.massValue*(10**self.scaleMassExp)):f}") self.volumeRawKG = float( f"{float(self.volValue*(10**self.scaleVolExp)):f}") self.meanRadius = self.meanRadius / (10**(self.scaleSizeExp)) self.equaRadius = self.equaRadius / (10**(self.scaleSizeExp)) #self.distanceFromSunInAU = self.distanceFromSunInAU / (10**(scale_dist)) # NOTE: you should scale moons with the planet accordingly # scale_size: float = 0.5,scale_mass: float = 8.5, scale_vol: float = 8.5, scale_dist: float = 4.2, debug: bool = False if do_moons: [ i.scale_moon(scale_data=scale_data, debug=debug) for i in self.moonData ] print( f"INFO: {self.englishName} scaled values [meanRadius -> {self.meanRadius}] [equaRadius -> {self.equaRadius}] [semimajorAxis -> {self.semimajorAxis}] [semiminorAxis -> {self.semiminorAxis}] [volValueRawKG -> {self.volumeRawKG}] [massRawKG -> {self.massRawKG}]" ) if debug else None return self
def __init__(self, name: str, scale_data: dict = None, debug: bool = False) -> Planet: """ Returns an object of class planet.Planet Parameters ---------- name: str English name of a planet in the Solar System scale_data: dict A dict which overrides any default settings with user provided settings (default: see below for format..) { "planet": { "scale_size": 0.5 }, "moon": { "debug": True, "scale_mass": 8.5 } } debug (bool): output useful debugging information """ self.default_scale_data = { "planet": { "debug": False, "scale_mass": 8.5, "scale_vol": 8.5, "scale_dist": 3.2, "scale_size": 1.5 }, "moon": { "debug": False, "scale_mass": 8.5, "scale_vol": 8.5, "scale_dist": 4.2, "scale_size": 1.5 } } self.user_scale_data = self.default_scale_data if scale_data == None else utilz.merge_attributes( self.default_scale_data, scale_data) _planet = data.get_planet_data(name) for k in _planet.keys(): print( f"INFO: adding attribute for planet {_planet['englishName']} ({k}) with value ({_planet[k]}) to {_planet['englishName']}" ) if debug else None setattr(self, k, _planet[k]) self.semiminorAxis = round(derive_semiminor_axis(self)) self.semimajorAxis = float(self.semimajorAxis) # NOTE: hack to avoid IDE errors, key is dynamically set from returned `planet` JSON object self.moons = self.moons self.vol = self.vol self.mass = self.mass self.sideralOrbit = self.sideralOrbit if self.moons == None: self.moonData = [] else: self.moonData = [] for moon in self.moons: if moon == None: print( f"INFO: the moon {moon} is not parseable, it will be skipped in plotting" ) if debug else None continue moonobj = Moon(moon['rel'], debug=debug) if not hasattr(moonobj, 'id') or not hasattr( moonobj, 'semimajorAxis') or not hasattr( moonobj, 'semiminorAxis') or not hasattr( moonobj, 'equaRadius') or not hasattr( moonobj, 'meanRadius') or not hasattr( moonobj, 'vol') or not hasattr( moonobj, 'mass'): print( f"INFO: the moon with relational URL {moon['rel']} is missing required attributes, it will be skipped in plotting" ) if debug else None continue # TODO: do filtering based on attribute limits, in blender module... print(f"INFO: adding moon with relational URL {moon['rel']}" ) if debug else None self.moonData.append(moonobj) # scales are zeroed on initialization and updated when scale_planets, or scale_planet is called against the object self.scaleMassExp = 0.0 self.scaleSizeExp = 0.0 self.scaleDistExp = 0.0 self.scaleVolExp = 0.0 # mass and volume values self.volValue = self.vol['volValue'] self.volExponent = self.vol['volExponent'] self.massValue = self.mass['massValue'] self.massExponent = self.mass['massExponent'] self.volumeRawKG = float( f"{float(self.volValue*(10**self.volExponent)):f}") self.massRawKG = float( f"{float(self.massValue*(10**self.massExponent)):f}") ############################################################################################################ # NOTE: calculate distance from sun in AU # # NOTE: calculate harmonic frequency value # # NOTE: AU value for orbital harmonies set during scale to properly capture scaled AU and harmonic values # # SOURCE km->au: https://www.wolframalpha.com/input/?i=1+km+in+AU # # SOURCE au->km: https://www.wolframalpha.com/input/?i=1+AU+in+km # # 1.496*(10**(8-scale_exp)) -> 1 au in km (scaled) # # 6.685*(10**-(9-scale_exp)) -> 1 km in au (scaled) # ############################################################################################################ self.distanceFromSunInAU = float( f"{float(self.semimajorAxis*( 6.685 * (10**-float(9) ) )):f}") self.harmonicFrequency = float( f"{float((self.distanceFromSunInAU**3)/(self.sideralOrbit**2)):f}") self.keys = list(_planet.keys()) + list( ('semiminorAxis', 'volValue', 'volExponent', 'massValue', 'massExponent', 'volumeRawKG', 'massRawKG', 'distanceFromSunInAU', 'harmonicFrequency', 'scaleMassExp', 'scaleSizeExp', 'scaleDistExp', 'scaleVolExp')) self.__class__._instances.append(self)