def NASAorbit(planet, sma, per, tilt = Quantity.below(90), Float=Quantity.fromDecimal, u=day, Mm=mega*metre, O=Orbit, S=Spin, **what): # no eccentricities supplied ... but they are all bound orbits ... # no tilt supplied, aside from retrograde or not ... if per < 0: tilt, per = tilt + 90, -per # no error bars supplied, but all periods gave two decimal places # sma is really radius / (1 - eccentricity), but endure it and let per's error-bar infect it return O(planet, sma * Mm, S(Float(per, 2, None, u), tilt), **what)
def NASAorbit(planet, sma, per, tilt=Quantity.below(90), Float=Quantity.fromDecimal, u=day, Mm=mega * metre, O=Orbit, S=Spin, **what): # no eccentricities supplied ... but they are all bound orbits ... # no tilt supplied, aside from retrograde or not ... if per < 0: tilt, per = tilt + 90, -per # no error bars supplied, but all periods gave two decimal places # sma is really radius / (1 - eccentricity), but endure it and let per's error-bar infect it return O(planet, sma * Mm, S(Float(per, 2, None, u), tilt), **what)
def __init__(self, period, tilt=Quantity.below(90), **what): """Initialises a Spin object. Takes two positional arguments: period -- a Quantity with dimensions of time; the period of the rotation described; stored as self.period. tilt -- angle, in degrees, between the axis of spin and some fixed direction provided by your context; a.k.a. inclination. Should lie between 0 and 90. Default is an error bar covering this whole range, meaning `unspecified'. Is stored as self.tilt; can be accessed as an angle value (i.e. multiplied by arc.degree) as self.inclination. Takes arbitrary keyword arguments after the manner of Object (q.v.). """ self.__upinit(**what) self.period, self.tilt = self.__time(period), tilt
def __init__(self, period, tilt=Quantity.below(90), **what): """Initialises a Spin object. Takes two positional arguments: period -- a Quantity with dimensions of time; the period of the rotation described; stored as self.period. tilt -- angle, in degrees, between the axis of spin and some fixed direction provided by your context; a.k.a. inclination. Should lie between 0 and 90. Default is an error bar covering this whole range, meaning `unspecified'. Is stored as self.tilt; can be accessed as an angle value (i.e. multiplied by arc.degree) as self.inclination. Takes arbitrary keyword arguments after the manner of Object (q.v.). """ self.__upinit(**what) self.period, self.tilt = self.__time(period), tilt
IAisland('Baffin', .2016), IAisland('Japan', .142726, IAisland('Honshu', .091278), IAisland('Kyushu', .014791)), IAisland('Java', .048504), IAisland('Britain', .09422, IAisland('Great Britain', .088133)), IAisland('Ireland', .027135), IAisland('Philipines', .115707), IAisland('Cuba', .044218), IAisland('Ceylon', .025332), IAisland('New Zealand', .103736), IAisland('Iceland', .039768), IAisland('Formosa', .013855)), name = 'Land', height = Quantity.below(8840, metre, mean=840)), # misc other data: rainfall = .125e18 * kg / year, # but c. half a million km**3/year according to # http://www.globalchange.umich.edu/globalchange2/current/lectures/freshwater_supply/freshwater.html flattening = 1 / 298.25, albedo = .39, # so 61% of incident radiation is absorbed # but total solar power available at surface is 1/8 of that in space: # http://www.physorg.com/news117649731.html # This may be about which frequencies solar panels can use. nature = { 'Land': .292, 'Ocean': .708 }, # TODO: merge into SurfacePart data ! material = "basalt, granite, water", magnetism = Object( sampled = 'London, 1960', horizontal = 1.87e-5 * Tesla,
def NASelement(name, symbol, Z, A, isos=None, abundance=None, melt=None, boil=None, density=None, **what): """Create an Element based on my Nuffield Advanced Data book's data. Required arguments: name -- string giving the full name of the element. symbol -- string giving the (one or two letter) symbol of the element. Z -- atomic number. Optional arguments: A -- molar mass * mol / g; a.k.a. atomic mass / AMU (default, None, means unknown). isos -- description of isotopes (see below); default is None. abundance -- relative terrestrial abundance, scaled to make Si score 100; default is None, indicating an artificial element. melt -- melting temperature / K boil -- boiling temperature / K density -- in g/cc at 298K; or a tuple (d, T), d in g/cc at T as liquid plus any further keyword arguments, to taste. See Element's constructor for further details; it receives a suitably scaled abundance. I have, rather arbitrarily, supposed that the phase change temperatures given in the NAS data book generally have an error bar of +/- half a Kelvin, except where marked as 'uncertain' (five K) or 'highly uncertain' (fifty K if the cited value's last two digits are zeros, otherwise ten K). Roughly as arbitrarily, where several forms of the elment are listed, I've used the lowest melting point and highest boiling point, ignoring any phase changes between forms and listing any sublimation (typically relevant only to one form, not the one whose melting and boiling are used) separately as sublime. The description of isotopes, if given, should either be a list of atomic mass numbers for which an isotope is known (for artificial elements and those natural radioactives whose isotopic composition varies wildly) or a mapping from known atomic mass numbers to relative abundances (or to None for those radioactive isotopes which normally have negligible abundance). If the sum of these relative abundances isn't 1, they'll be (fudged to make it 100 - because the NAS book is a bit off on some elements - and then) scaled down to make it 1. Both the element's terrestrial abundance and the relative abundance of its isotopes will be given an error bar, if they don't already have one, to accord with the limited precision indicated in the NAS table. """ if abundance is None: what['abundance'] = None # artificial elements else: try: abundance.width except AttributeError: # need an error bar (guess: two decimal places of precision) abundance = Quantity.fromSigFigs(abundance, 2) # NAS data book gives abundances relative to Silicon = 100, but notes # that Silicon's true abundance is believed to be 27.72 % what['abundance'] = abundance * .2772 try: A.width except AttributeError: # give it an error bar try: isos[:] # radioactive/artificial elements except TypeError: A = Float(A, 4) # real ones else: A = About(A, .5 * max(1, max(isos) - min(isos))) if density is not None: if not isinstance(density, Quantity): try: density, temp = density except TypeError: temp = 298 * Kelvin else: temp *= Kelvin density = Float(density, 2, units=gram / cc, measured=temp) what['density'] = density temp = {} if melt is not None: try: melt.width except AttributeError: melt = Float(melt, 1) temp['melt'] = melt * Kelvin if boil is not None: try: boil.width except AttributeError: boil = Float(boil, 1) temp['boil'] = boil * Kelvin try: temp['sublime'] = what['sublime'] except KeyError: pass else: del what['sublime'] if temp: T = Temperatures(**temp) else: T = None ans = Element(name, symbol, Z, A, T, **what) try: isos[:] except TypeError: try: isos.update except AttributeError: pass # no information else: # dictionary: { isotope: relative abundance } weights = [x for x in isos.values() if x] total = sum(weights) if total == 1: fix, scale = None, 1 # weights given as fractions else: # Otherwise, assume given as percentages; but the NAS table # has several entries that don't sum accurately to 100. scale = .01 if total == 100: fix = None else: # bodge: blur the non-tiny weights to make it all sum right ... assert 80 < total < 120, "Perhaps these aren't percentages after all" fix = 1 + (100 - total) * Quantity.below(2) \ / sum(x for x in weights if x > 1) # Perhaps we can improve on this ... for k, v in isos.items(): iso = Isotope(Z, k - Z) if v: unit = 1 if v < 1: while unit > v: unit = unit * .1 unit = unit * .1 if fix and v > 1: v = v * fix # bodge v = About(v, unit * .01) iso.abundance = v * scale else: # sequence: known isotopes for k in isos: Isotope(Z, k - Z) return ans
def NASelement(name, symbol, Z, A, isos=None, abundance=None, melt=None, boil=None, **what): """Create an Element based on my Nuffield Advanced Data book's data. Required arguments: name -- string giving the full name of the element. symbol -- string giving the (one or two letter) symbol of the element. Z -- atomic number. Optional arguments: A -- molar mass * mol / g; a.k.a. atomic mass / AMU (default, None, means unknown). isos -- description of isotopes (see below); default is None. abundance -- relative terrestrial abundance, scaled to make Si score 100; default is None, indicating an artificial element. melt -- melting temperature / K boil -- boiling temperature / K plus any further keyword arguments, to taste. See Element's constructor for further details; it receives a suitably scaled abundance. I have, rather arbitrarily, supposed that the phase change temperatures given in the NAS data book generally have an error bar of +/- half a Kelvin, except where marked as 'uncertain' (five K) or 'highly uncertain' (fifty K if the cited value's last two digits are zeros, otherwise ten K). Roughly as arbitrarily, where several forms of the elment are listed, I've used the lowest melting point and highest boiling point, ignoring any phase changes between forms and listing any sublimation (typically relevant only to one form, not the one whose melting and boiling are used) separately as sublime. The description of isotopes, if given, should either be a list of atomic mass numbers for which an isotope is known (for artificial elements and those natural radioactives whose isotopic composition varies wildly) or a mapping from known atomic mass numbers to relative abundances (or to None for those radioactive isotopes which normally have negligible abundance). If the sum of these relative abundances isn't 1, they'll be (fudged to make it 100 - because the NAS book is a bit off on some elements - and then) scaled down to make it 1. Both the element's terrestrial abundance and the relative abundance of its isotopes will be given an error bar, if they don't already have one, to accord with the limited precision indicated in the NAS table. """ if abundance is None: what["abundance"] = None # artificial elements else: try: abundance.width except AttributeError: # need an error bar (guess: two decimal places of precision) abundance = Quantity.fromSigFigs(abundance, 2) # NAS data book gives abundances relative to Silicon = 100, but notes # that Silicon's true abundance is believed to be 27.72 % what["abundance"] = abundance * 0.2772 try: A.width except AttributeError: # give it an error bar try: isos[:] # radioactive/artificial elements except TypeError: A = Quantity.fromDecimal(A, 4) # real ones else: A = Quantity.within(A, 0.5 * max(1, max(isos) - min(isos))) temp = {} if melt is not None: try: melt.width except AttributeError: melt = Quantity.fromDecimal(melt, 1) temp["melt"] = melt * Kelvin if boil is not None: try: boil.width except AttributeError: boil = Quantity.fromDecimal(boil, 1) temp["boil"] = boil * Kelvin try: temp["sublime"] = what["sublime"] except KeyError: pass else: del what["sublime"] if temp: T = Temperatures(**temp) else: T = None ans = Element(name, symbol, Z, A, T, **what) try: isos[:] except TypeError: try: isos.update except AttributeError: pass # no information else: # dictionary: { isotope: relative abundance } weights = filter(None, isos.values()) total = sum(weights) if total == 1: fix, scale = None, 1 # weights given as fractions else: # Otherwise, assume given as percentages; but the NAS table # has several entries that don't sum accurately to 100. scale = 0.01 if total == 100: fix = None else: # bodge: blur the non-tiny weights to make it all sum right ... assert 80 < total < 120, "Perhaps these aren't percentages after all" fix = 1 + (100 - total) * Quantity.below(2) / sum(filter(lambda x: x > 1, weights)) # Perhaps we can improve on this ... for k, v in isos.items(): iso = Isotope(Z, k - Z) if v: unit = 1 if v < 1: while unit > v: unit = unit * 0.1 unit = unit * 0.1 if fix and v > 1: v = v * fix # bodge v = Quantity.within(v, unit * 0.01) iso.abundance = v * scale else: # sequence: known isotopes for k in isos: Isotope(Z, k - Z) return ans
IAisland('Baffin', .2016), IAisland('Japan', .142726, IAisland('Honshu', .091278), IAisland('Kyushu', .014791)), IAisland('Java', .048504), IAisland('Britain', .09422, IAisland('Great Britain', .088133)), IAisland('Ireland', .027135), IAisland('Philipines', .115707), IAisland('Cuba', .044218), IAisland('Ceylon', .025332), IAisland('New Zealand', .103736), IAisland('Iceland', .039768), IAisland('Formosa', .013855)), name = 'Land', height = Quantity.below(8840, metre, mean=840)), # misc other data: rainfall = .125e18 * kg / year, # but c. half a million km**3/year according to # http://www.globalchange.umich.edu/globalchange2/current/lectures/freshwater_supply/freshwater.html flattening = 1 / 298.25, albedo = .39, # so 61% of incident radiation is absorbed # but total solar power available at surface is 1/8 of that in space: # http://www.physorg.com/news117649731.html # This may be about which frequencies solar panels can use. nature = { 'Land': .292, 'Ocean': .708 }, # TODO: merge into SurfacePart data ! material = "basalt, granite, water", magnetism = Object( sampled = 'London, 1960', horizontal = 1.87e-5 * Tesla,
had a perfectly good word for that - chaos - and Eris wasn't particularly associated with it, aside from it tending to be a consequence of her vicious trouble-making. As Steve Linley put it, Eris is identified as 'warmonger, the cause of conflict, the source of competitive rivalry. Any attempt to euphemise, mollify or glamorise her nature is naive.' For further details, see: * http://www.pantheon.org/articles/e/eris.html * http://homepage.mac.com/cparada/GML/Eris.html """)) Dysnomia = Planetoid(name="Dysnomia", surface=Spheroid(75 * kilo * metre), # < 150 km orbit=Orbit(Eris, About(37.37, .15, mega * metre), Spin(About(15.774, .002, day), About(142, 3)), Quantity.below(.013)), discovery=Discovery("M. E. Brown, M. A. van Dam, A. H. Bouchez, D. Le Mignant", 2005, telescope="Keck", note="""2005, September 10 images. Initially nicknamed Gabrielle after Xena's side-kick. Discovered using laser guide star adaptive optics. Its discoverers translate 'Dysnomia' as 'lawlessness', punning on the name, Lucy Lawless, of the actress who played Xena. http://www.pantheon.org/articles/d/dysnomia.html """)) # I take Kupier and Oort from a diagram in New Scientist [2004/Dec/25th, p46] # using a logarithmic scale for radius. Like Asteroid, they're rather # imprecise. Separate nasa.gov pages refined the Kuiper orbit: "it has a rather
transformative power of chaos, but it should be noted that the ancient Greeks had a perfectly good word for that - chaos - and Eris wasn't particularly associated with it, aside from it tending to be a consequence of her vicious trouble-making. As Steve Linley put it, Eris is identified as 'warmonger, the cause of conflict, the source of competitive rivalry. Any attempt to euphemise, mollify or glamorise her nature is naive.' For further details, see: * http://www.pantheon.org/articles/e/eris.html * http://homepage.mac.com/cparada/GML/Eris.html """)) Dysnomia = Planetoid( name="Dysnomia", surface=Spheroid(75 * kilo * metre), # < 150 km orbit=Orbit(Eris, About(37.37, .15, mega * metre), Spin(About(15.774, .002, day), About(142, 3)), Quantity.below(.013)), discovery=Discovery( "M. E. Brown, M. A. van Dam, A. H. Bouchez, D. Le Mignant", 2005, telescope="Keck", note="""2005, September 10 images. Initially nicknamed Gabrielle after Xena's side-kick. Discovered using laser guide star adaptive optics. Its discoverers translate 'Dysnomia' as 'lawlessness', punning on the name, Lucy Lawless, of the actress who played Xena. http://www.pantheon.org/articles/d/dysnomia.html """)) # I take Kupier and Oort from a diagram in New Scientist [2004/Dec/25th, p46]