def Arrhenius(self, k25, Ea, Tk, deltaS=None, Hd=None): if ( (deltaS is not None) & (Hd is not None) ): arg1 = k25 * np.exp((Ea * (Tk.to('Kelvin', equivalencies=u.temperature() ) - 298.15*u.Kelvin)) / (298.15*u.Kelvin * c.R * Tk.to('Kelvin', equivalencies=u.temperature() ))) arg2 = 1.0 + np.exp( (298.15*u.Kelvin * deltaS - Hd) / (298.15 * u.Kelvin * c.R) ) arg3 = 1.0 + np.exp((Tk.to('Kelvin', equivalencies=u.temperature() ) * deltaS - Hd) / (Tk.to('Kelvin', equivalencies=u.temperature() ) * c.R)) return (arg1 * arg2) / arg3 else: return k25 * np.exp((Ea * (Tk.to('Kelvin', equivalencies=u.temperature() ) - 298.15*u.Kelvin)) / (298.15*u.Kelvin * c.R * Tk.to('Kelvin', equivalencies=u.temperature() )))
def __calcVPandSo(self, temp, rH, Pressure): self.__temp = temp self.__rH = rH if rH <= 1 else 0.999 self.__Pressure = Pressure self.__SVP = ((6.1094 * np.exp( (17.625 * (self.__temp.value)) / (243.04 + (self.__temp.value)))) * (1.00071 * np.exp(0.0000045 * (self.__Pressure.to("hPa").value))) ) * u.hectopascal self.__VP = self.__SVP * self.__rH self.__VPD = self.__SVP - self.__VP self.__rf = self.r_one / ( 1.0 - self.__rH * self.__SVP / self.Pressure * (1.0 - self.r_one / self.r_two) ) #Die Gaskonstante der feuchten Luft self.__densOfAir = (self.__Pressure) / (self.__rf * self.__temp.to( 'Kelvin', equivalencies=u.temperature())) self.__latHeatVapWater = ( (50.09 - 0.9298 * (self.__temp.to('Kelvin', equivalencies=u.temperature()).value / 1000) - 65.19 * (self.__temp.to('Kelvin', equivalencies=u.temperature()).value / 1000)**2) * u.kJ / u.mol) / (18.0153 * u.g / u.mol) # 13 from Moualeu-Ngangua 2016 self.__slopeOfSatPress = ( (17.502 * (240 * u.Celsius).to('Kelvin', equivalencies=u.temperature()) * self.__VPD) / ((240 * u.Celsius).to('Kelvin', equivalencies=u.temperature()) + self.__temp.to('Kelvin', equivalencies=u.temperature()))**2).to( u.hPa / u.Kelvin) self.__psyConst = (self.specHeatofAir * self.__Pressure) / ( (self.__latHeatVapWater) * 0.622) self.__E_ = self.__slopeOfSatPress / self.__psyConst self.__aH = (self.__VP / (self.r_two * self.__temp.to( 'Kelvin', equivalencies=u.temperature()))).to(u.g / u.m**3) self.__sH = (((18.01528 / 28.9644) * self.__VP) / (self.__Pressure - (1 - 18.01528 / 28.9644) * self.__VP)).to(u.g / u.kg) self.__mH = self.__VP / self.__Pressure #emissivity of atmosphere (D4 from leining (1995): self.__emissivity_atmo = 0.642 * ( self.__VP.to(u.Pa).value / self.__temp.to( 'Kelvin', equivalencies=u.temperature()).value)**(1.0 / 7.0) self.__molar_mass_humid_air = self.__densOfAir * ( (c.R * self.__temp.to('Kelvin', equivalencies=u.temperature())) / self.__Pressure) self.__mfco2 = (( ((self.__Pressure * self.__Cs) / (c.R * self.__temp.to('Kelvin', equivalencies=u.temperature()))) * 44.00964 * (u.g / u.mol))) / (self.__densOfAir)
def defaultWeather(altitude): """Set default local weather conditions if they are missing. Parameters ---------- weather : `lsst.afw.coord.Weather` Class containing the measured temperature, pressure, and humidity at the observatory during an observation altitude : `astropy.units.Quantity` The altitude of the observatory, in meters. Returns ------- default : `lsst.afw.coord.Weather` Updated Weather class with any `nan` values replaced by defaults. """ if isinstance(altitude, units.quantity.Quantity): altitude2 = altitude else: altitude2 = altitude*units.meter p0 = 101325.*units.pascal # sea level air pressure g = 9.80665*units.meter/units.second**2 # typical gravitational acceleration at sea level R0 = 8.31447*units.Joule/(units.mol*units.Kelvin) # gas constant T0 = 19.*units.Celsius # Typical sea-level temperature lapseRate = -6.5*units.Celsius/units.km # Typical rate of change of temperature with altitude M = 0.0289644*units.kg/units.mol # molar mass of dry air temperature = T0 + lapseRate*altitude2 temperatureK = temperature.to(units.Kelvin, equivalencies=units.temperature()) pressure = p0*np.exp(-(g*M*altitude2)/(R0*temperatureK)) humidity = 40. # Typical humidity at many observatory sites. weather = Weather((temperature/units.Celsius).value, (pressure/units.pascal).value, humidity) return weather
def __init__(self, *, name, value, idb_info, engineering, unit, order=-1): """Create a EngineeringParameter object. Parameters ---------- value : `int` | `list` The raw values. engineering : `int` | `list` The engineering values. """ super(EngineeringParameter, self).__init__(name=name, value=value, idb_info=idb_info, order=order) self.unit = unit convert = False if unit == 'degC': unit = 'deg_C' convert = 'K' if unit is not None and unit != '' and engineering is not None: try: engineering = engineering * u.Unit(unit) if convert == 'K': engineering = engineering.to(convert, equivalencies=u.temperature()) except ValueError: raise NotImplementedError(f"Add unit support: for {unit}") self.engineering = engineering
def defaultWeather(altitude): """Set default local weather conditions if they are missing. Parameters ---------- weather : `lsst.afw.coord.Weather` Class containing the measured temperature, pressure, and humidity at the observatory during an observation altitude : `astropy.units.Quantity` The altitude of the observatory, in meters. Returns ------- `lsst.afw.coord.Weather` Updated Weather class with any `nan` values replaced by defaults. """ if isinstance(altitude, units.quantity.Quantity): altitude2 = altitude else: altitude2 = altitude * units.meter p0 = 101325. * units.pascal # sea level air pressure g = 9.80665 * units.meter / units.second**2 # typical gravitational acceleration at sea level R0 = 8.31447 * units.Joule / (units.mol * units.Kelvin) # gas constant T0 = 19. * units.Celsius # Typical sea-level temperature lapseRate = -6.5 * units.Celsius / units.km # Typical rate of change of temperature with altitude M = 0.0289644 * units.kg / units.mol # molar mass of dry air temperature = T0 + lapseRate * altitude2 temperatureK = temperature.to(units.Kelvin, equivalencies=units.temperature()) pressure = p0 * np.exp(-(g * M * altitude2) / (R0 * temperatureK)) humidity = 40. # Typical humidity at many observatory sites. weather = Weather((temperature / units.Celsius).value, (pressure / units.pascal).value, humidity) return weather
def blackbody_lambda(wavelength, temperature): """ Calculate the blackbody spectral density per unit wavelength. Parameters ---------- wavelength : `~astropy.units.Quantity` Wavelength array to evaluate on. temperature : `~astropy.units.Quantity` Blackbody temperature. """ # Convert to units for calculations, also force double precision with u.add_enabled_equivalencies(u.spectral() + u.temperature()): freq = u.Quantity(wavelength, u.Hz, dtype=np.float64) temp = u.Quantity(temperature, u.K, dtype=np.float64) log_boltz = const.h * freq / (const.k_B * temp) boltzm1 = np.expm1(log_boltz) bb_nu = (2.0 * const.h * freq ** 3 / (const.c ** 2 * boltzm1)) flam = u.erg / (u.cm**2 * u.s * u.AA) flux = bb_nu.to(flam, u.spectral_density(wavelength)) return flux / u.sr # Add per steradian to output flux unit
def prepare_quantity(value, units=None, name_val=None): """ Convert the input to the required units The function verifies that the input has the right units and converts it to the desired units. For example, if a value is introduced in km but posterior frequencies require this value to be in meters, this function would be called with `units=u.m` """ if value is None: return None # If the units of the value are a temperature if isinstance(value, u.Quantity): if units in [u.K, u.deg_C, u.Kelvin, u.Celsius, u.imperial.deg_F]: return value.to(units, equivalencies=u.temperature()).value else: return value.to(units).value # Process numbers elif isinstance(value, numbers.Number) and units is not None: return value # Process arrays and tuples elif isinstance(value, np.ndarray) and units is not None: return value elif isinstance(value, list) and units is not None: return np.array([prepare_quantity(v, units, name_val) for v in value]) elif isinstance(value, tuple) and units is not None: return np.array([prepare_quantity(v, units, name_val) for v in value]) else: raise ValueError('%s has not the correct format. It must be a value,' 'sequence, array, or a Quantity with %s units' % (name_val, str(units)))
def make_emission_from_emissivity(temp, emiss_src_spec): """ Create an emission SourceSpectrum using a blackbody and an emissivity curve Parameters ---------- temp : float, Quantity [Kelvin] If float, then must be in Kelvin emiss_src_spec : synphot.SpectralElement An emissivity response curve in the range [0..1] Returns ------- flux : synphot.SourceSpectrum """ if isinstance(temp, u.Quantity): temp = temp.to(u.Kelvin, equivalencies=u.temperature()).value if emiss_src_spec is None: logging.warning("Either emission or emissivity must be set") flux = None else: flux = SourceSpectrum(BlackBody1D, temperature=temp) flux.meta["solid_angle"] = u.sr**-1 flux = flux * emiss_src_spec flux.meta["history"] = [ "Created from Blackbody curve. Units are to be" " understood as per steradian" ] return flux
def compound_models_with_input_eq(): m1 = astmodels.Gaussian1D(10 * u.K, 11 * u.arcsec, 12 * u.arcsec) m1.input_units_equivalencies = {'x': u.parallax()} m2 = astmodels.Gaussian1D(5 * u.s, 2 * u.K, 3 * u.K) m2.input_units_equivalencies = {'x': u.temperature()} return [m1 | m2, m1 & m2, m1 + m2]
def evaluate(self, x, temperature, bolometric_flux, wave_0, beta): if isinstance(temperature, u.Quantity): temperature = temperature.to(u.K, equivalencies=u.temperature()) else: temperature = u.Quantity(temperature, u.K) # We normalize the returned blackbody so that the integral would be # unity, and we then multiply by the bolometric flux. A normalized # blackbody has f_nu = pi * B_lambda / (sigma * T^4), which is what we # calculate here. We multiply by the bolometric # flux to get the normalization right. flambda = ((np.pi * u.sr * blackbody_nu(x, temperature) / const.sigma_sb / temperature ** 4).to(1 / u.Hz) * bolometric_flux) tau = (wave_0 / x)**beta fnu = np.exp(-tau) * fnu # If the bolometric_flux parameter has no unit, we should drop the 1/Hz # and return a unitless value. This occurs for instance during fitting, # since we drop the units temporarily. if hasattr(bolometric_flux, 'unit'): return flambda else: return flambda.value
def test_i_tmin_kelvin(self): """tests behavior when compute_i_tmin is called with kelvin temps""" frac = np.arange(0.0, 1.0, 0.2) tmin = frac * (gsi.TMIN_MAX - gsi.TMIN_MIN) + gsi.TMIN_MIN tmin = tmin.to(u.K, equivalencies=u.temperature()) i_tmin = gsi.calc_i_tmin(tmin) self.assertTrue(np.all(np.abs(i_tmin - frac) < 1e-5))
def assim(self, CO): if CO.unit.physical_type == 'mass': gaseousVolume = ( (CO / (44.0095 * (u.g / u.mol))) * c.R * self.temp.to( 'Kelvin', equivalencies=u.temperature())) / self.Pressure self.__outflow = self.__outflow - gaseousVolume.cgs self.mfco2 = ( (self.mfco2 * self.massAir) - CO) / (self.massAir - CO) elif CO.unit.physical_type == 'amount of substance': gaseousVolume = (CO * c.R * self.temp.to( 'Kelvin', equivalencies=u.temperature())) / self.Pressure self.__outflow = self.__outflow - gaseousVolume.cgs self.Cs = ((self.Cs * (self.massAir / self.molar_mass_humid_air)) - CO) / ( (self.massAir / self.molar_mass_humid_air) - CO) else: raise ValueError('Can only accept mass or moles as argument') self.__calcMasses__()
def oneten_nfdrs (Temp, RH, SOW): """One and ten hour fuel moisture computation using 1978 NFDRS method. This function adjusts standard exposed instrument readings (for temperature and RH) from 4.5 feet off the ground in a shelter to "fuel level" as per Table 6 in [1]. "State of the weather" code definitions: SOW = 0 : Clear sky (0.0-0.1 cloud cover) SOW = 1 : Scattered (0.1-0.5 cloud cover) SOW = 2 : Broken (0.6-0.9 cloud cover) anything else : Overcast (0.9-1.0 cloud cover) The scaling factors applied to equilibrium moisture content to obtain one and ten hour fuel moistures (e.g., in the return statement) have the following caveat: This model works well for early afternoons in strong continental areas at the approximate latitude of Nebraska in the late summer. It tends to underpredict stick readings under other conditions. See [1] for further details. [1] Bradshaw, Larry S., John E. Deeming, Robert E. Burgan, and Jack D. Cohen. 1984. The 1978 National Fire-Danger Rating System: Technical Documentation. http://www.treesearch.fs.fed.us/pubs/29615. Parameters ---------- Temp : array : degF RH : array : pct SOW : array : dimensionless Returns ------- fm : array : pct Tuple containing the (1-hr, 10-hr) fuel moistures. """ # Determine the temperature and rh factors to adjust for fuel temperatures if SOW == 0: tfact = 25.0 * iu.deg_F hfact = 0.75 if SOW == 1: tfact = 19.0 * iu.deg_F hfact = 0.83 if SOW == 2: tfact = 12.0 * iu.deg_F hfact = 0.92 else: tfact = 5.0 * iu.deg_F hfact = 1.0 if Temp.unit != iu.deg_F : Temp = Temp.to(iu.deg_F, u.temperature()) emc = eqmc(tfact + Temp, hfact * RH) return (1.03*emc, 1.28*emc)
def oneten_nfdrs(Temp, RH, SOW): """One and ten hour fuel moisture computation using 1978 NFDRS method. This function adjusts standard exposed instrument readings (for temperature and RH) from 4.5 feet off the ground in a shelter to "fuel level" as per Table 6 in [1]. "State of the weather" code definitions: SOW = 0 : Clear sky (0.0-0.1 cloud cover) SOW = 1 : Scattered (0.1-0.5 cloud cover) SOW = 2 : Broken (0.6-0.9 cloud cover) anything else : Overcast (0.9-1.0 cloud cover) The scaling factors applied to equilibrium moisture content to obtain one and ten hour fuel moistures (e.g., in the return statement) have the following caveat: This model works well for early afternoons in strong continental areas at the approximate latitude of Nebraska in the late summer. It tends to underpredict stick readings under other conditions. See [1] for further details. [1] Bradshaw, Larry S., John E. Deeming, Robert E. Burgan, and Jack D. Cohen. 1984. The 1978 National Fire-Danger Rating System: Technical Documentation. http://www.treesearch.fs.fed.us/pubs/29615. Parameters ---------- Temp : array : degF RH : array : pct SOW : array : dimensionless Returns ------- fm : array : pct Tuple containing the (1-hr, 10-hr) fuel moistures. """ # Determine the temperature and rh factors to adjust for fuel temperatures if SOW == 0: tfact = 25.0 * iu.deg_F hfact = 0.75 if SOW == 1: tfact = 19.0 * iu.deg_F hfact = 0.83 if SOW == 2: tfact = 12.0 * iu.deg_F hfact = 0.92 else: tfact = 5.0 * iu.deg_F hfact = 1.0 if Temp.unit != iu.deg_F: Temp = Temp.to(iu.deg_F, u.temperature()) emc = eqmc(tfact + Temp, hfact * RH) return (1.03 * emc, 1.28 * emc)
def test_oneten_units(self): """Checks for proper temperature units conversion""" rh = 50 * u.pct tc = 30 * u.deg_C tf = tc.to(iu.deg_F, u.temperature()) ot_c = fm.oneten_nfdrs(tc, rh, 0) ot_f = fm.oneten_nfdrs(tf, rh, 0) self.assertLess(np.abs(ot_c[0] - ot_f[0]), 0.1 * u.pct)
def test_oneten_units(self): """Checks for proper temperature units conversion""" rh = 50*u.pct tc = 30*u.deg_C tf = tc.to(iu.deg_F, u.temperature()) ot_c = fm.oneten_nfdrs(tc,rh,0) ot_f = fm.oneten_nfdrs(tf,rh,0) self.assertLess( np.abs(ot_c[0]-ot_f[0]), 0.1*u.pct)
def __add__(self, other): if isinstance(other, vap) != True: raise AttributeError('can only add objects of type vap') tempSelf = deepcopy(self) tempSelf.volume = tempSelf.volume + other.volume tempSelf.__massAir = tempSelf.massAir + other.massAir tempSelf.temp = ( (self.temp.to('Kelvin', equivalencies=u.temperature()) * self.massAir + other.temp.to( 'Kelvin', equivalencies=u.temperature()) * other.massAir) / tempSelf.massAir).to('Celsius', equivalencies=u.temperature()) tempSelf.aH = (self.aH * self.volume + other.aH * other.volume) / tempSelf.volume tempSelf.Cs = (self.Cs * self.volume + other.Cs * other.volume) / tempSelf.volume tempSelf.__calcMasses__() return tempSelf
def blackbody_nu(in_x, temperature): """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`. .. note:: Use `numpy.errstate` to suppress Numpy warnings, if desired. .. warning:: Output values might contain ``nan`` and ``inf``. Parameters ---------- in_x : number, array-like, or `~astropy.units.Quantity` Frequency, wavelength, or wave number. If not a Quantity, it is assumed to be in Hz. temperature : number or `~astropy.units.Quantity` Blackbody temperature. If not a Quantity, it is assumed to be in Kelvin. Returns ------- flux : `~astropy.units.Quantity` Blackbody monochromatic flux in :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`. Raises ------ ValueError Invalid temperature. ZeroDivisionError Wavelength is zero (when converting to frequency). """ # Convert to units for calculations, also force double precision with u.add_enabled_equivalencies(u.spectral() + u.temperature()): freq = u.Quantity(in_x, u.Hz, dtype=np.float64) temp = u.Quantity(temperature, u.K, dtype=np.float64) # Check if input values are physically possible if temp < 0: raise ValueError('Invalid temperature {0}'.format(temp)) if np.any(freq <= 0): # pragma: no cover warnings.warn('Input contains invalid wavelength/frequency value(s)', AstropyUserWarning) # Calculate blackbody flux bb_nu = (2.0 * const.h * freq**3 / (const.c**2 * np.expm1(const.h * freq / (const.k_B * temp)))) flux = bb_nu.to(FNU, u.spectral_density(freq)) return flux / u.sr # Add per steradian to output flux unit
def test_eqmc_units(self): """Checks for proper temperature units conversion""" rh = 50 * u.pct tc = 30 * u.deg_C tf = tc.to(iu.deg_F, u.temperature()) emc_c = fm.eqmc(tc, rh) emc_f = fm.eqmc(tf, rh) self.assertLess(np.abs(emc_c - emc_f), 0.1 * u.pct) self.assertEqual(emc_c.unit, u.pct)
def test_eqmc_units(self): """Checks for proper temperature units conversion""" rh = 50*u.pct tc = 30*u.deg_C tf = tc.to(iu.deg_F, u.temperature()) emc_c = fm.eqmc(tc, rh) emc_f = fm.eqmc(tf, rh) self.assertLess( np.abs(emc_c - emc_f), 0.1*u.pct) self.assertEqual(emc_c.unit, u.pct)
def blackbody_nu(in_x, temperature): """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`. .. note:: Use `numpy.errstate` to suppress Numpy warnings, if desired. .. warning:: Output values might contain ``nan`` and ``inf``. Parameters ---------- in_x : number, array-like, or `~astropy.units.Quantity` Frequency, wavelength, or wave number. If not a Quantity, it is assumed to be in Hz. temperature : number or `~astropy.units.Quantity` Blackbody temperature. If not a Quantity, it is assumed to be in Kelvin. Returns ------- flux : `~astropy.units.Quantity` Blackbody monochromatic flux in :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`. Raises ------ ValueError Invalid temperature. ZeroDivisionError Wavelength is zero (when converting to frequency). """ # Convert to units for calculations, also force double precision with u.add_enabled_equivalencies(u.spectral() + u.temperature()): freq = u.Quantity(in_x, u.Hz, dtype=np.float64) temp = u.Quantity(temperature, u.K, dtype=np.float64) # Check if input values are physically possible if temp < 0: raise ValueError('Invalid temperature {0}'.format(temp)) if np.any(freq <= 0): # pragma: no cover warnings.warn('Input contains invalid wavelength/frequency value(s)', AstropyUserWarning) # Calculate blackbody flux bb_nu = (2.0 * const.h * freq ** 3 / (const.c ** 2 * np.expm1(const.h * freq / (const.k_B * temp)))) flux = bb_nu.to(FNU, u.spectral_density(freq)) return flux / u.sr # Add per steradian to output flux unit
def update_response(attrname, old, new): # check whether the input variables have changed and update the response global response if not material_input.disabled: if str(material_input.value).lower() in all_materials: this_thickness = u.Quantity(material_thickness_input.value, material_thick_unit.value) this_density = u.Quantity(material_density_input.value, material_density_unit.value) this_material = Material(str(material_input.value).lower(), this_thickness, density=this_density) else: # if material not selected, just make a bogus material with no thickness this_material = Material('Al', 0 * u.mm) if not air_pressure_input.disabled: if air_pressure_unit.value == "atm": air_pressure = u.Quantity(air_pressure_input.value * const.atm, "Pa") elif air_pressure_unit.value == "torr": air_pressure = u.Quantity( air_pressure_input.value * const.atm / 760., "Pa") else: air_pressure = u.Quantity(air_pressure_input.value, air_pressure_unit.value) air_path_length = u.Quantity(air_thickness_input.value, air_thick_unit.value) air_temperature = u.Quantity(air_temperature_input.value, air_temp_unit.value).to( "Celsius", equivalencies=u.temperature()) air_density = density_ideal_gas(air_pressure, air_temperature) air = Material('air', air_path_length, density=air_density) else: # if air is not selected than just add bogus air with no thickness air = Material('air', 0 * u.mm, density=0 * u.g / u.cm**3) if not detector_material_input.disabled: if str(detector_material_input.value).lower() in all_materials: this_thickness = u.Quantity(detector_thickness_input.value, detector_thick_unit.value) this_density = u.Quantity(detector_density_input.value, detector_density_unit.value) this_detector = Material(str( detector_material_input.value).lower(), this_thickness, density=this_density) else: this_detector = None response = Response(optical_path=[this_material, air], detector=this_detector)
def convert_and_strip_units(quantity, output_unit=None, digit=10): """ Strips units and return the numerical value. Parameters ---------- quantity : int or float or list or None or ~astropy.units.quantity.Quantity Numerical quantity. Pass it without including units if default units are intended. output_unit : ~astropy.units.core.UnitBase or ~astropy.units.quantity.Quantity The default units in which the quantity is to be converted before extracting the value. Other Parameters ---------------- round: int round to that number of digit after conversion. Default ``10``. Set to ``None`` to disable. Returns ------- int or float or None or ~numpy.ndarray The numerical value extracted from ``quantity`` Examples -------- >>> convert_and_strip_units(4.5 * u.um, u.nm) <<< 4500.0 >>> convert_and_strip_units(200000 * (u.m)**-1, 1/u.cm) <<< 2000.0 Raises ------ TypeError Raised when ``quantity`` is a astropy.units quantity and ``output_unit`` is ``None``. """ if isinstance(quantity, u.Quantity): if output_unit in (u.deg_C, u.imperial.deg_F, u.K): quantity = quantity.to_value(output_unit, equivalencies=u.temperature()) elif isinstance(output_unit, (u.UnitBase, u.Quantity)): quantity = quantity.to_value(output_unit, equivalencies=u.spectral()) else: raise TypeError( "'output_unit' parameter is not a valid astropy unit: {0}".format( output_unit ) ) if digit: quantity = round(quantity, digit) return quantity
def transpire(self, Water): if Water.unit.physical_type == 'mass': gaseousVolume = ( (Water / (18.01528 * (u.g / u.mol))) * c.R * self.temp.to( 'Kelvin', equivalencies=u.temperature())) / self.Pressure self.__outflow = self.__outflow + gaseousVolume.cgs self.aH = ((self.aH * self.volume) + Water) / (self.volume + gaseousVolume) return (gaseousVolume) elif Water.unit.physical_type == 'amount of substance': gaseousVolume = (Water * c.R * self.temp.to( 'Kelvin', equivalencies=u.temperature())) / self.Pressure self.__outflow = self.__outflow + gaseousVolume.cgs self.mH = ( (self.mH * (self.massAir / self.molar_mass_humid_air)) + Water) / ( (self.massAir / self.molar_mass_humid_air) + Water) else: raise ValueError('Can only accept mass or moles as argument') self.__calcMasses__()
def nominal_pressure(elevation, airtemp=None): """Calculate the nominal pressure in a standard atmosphere. Uses a model with a linear decrease in temperature with elevation from sea level. For details, see https://en.wikipedia.org/wiki/Vertical_pressure_variation Parameters ---------- elevation : astropy.units.Quantity Elevation above sea level to use. airtemp : astropy.units.Quantity or None Air temperature at the specified elevation to use for the standard atmosphere. When None, assume 15C at sea level with a constant lapse rate. Returns ------- astropy.units.Quantity Pressure at the specified elevation in a standard atmosphere. """ # The atmosphere constant in astropy < 2.0 was renamed to atm in 2.0. try: P0 = astropy.constants.atm except AttributeError: # Fallback for astropy < 2.0. P0 = astropy.constants.atmosphere g = astropy.constants.g0 # Specific gas constant for air. R = 287.053 * u.J / (u.kg * u.K) # Atmospheric lapse rate. L = -6.5e-3 * u.K / u.m if airtemp is None: # Assume 15C at sea level. T0 = (15 * u.deg_C).to(u.K, equivalencies=u.temperature()) else: # Convert airtemp to K. T = airtemp.to(u.K, equivalencies=u.temperature()) # Estimate corresponding sea-level temperature. T0 = T - L * elevation return P0 * np.power(1 + elevation * L / T0, -g / (L * R))
def test_kelvin(self) : """check to ensure that we can calculate vp using Kelvin temps""" for method in satvp.vp_calcs.keys() : calc = satvp.vp_calcs[method] # only reason to explicitly convert to kPa is to ensure the precision # of the comparison is expressed in kPa. test_vp = calc.calc_vp(self.temp.to(u.K, equivalencies=u.temperature())).to(u.kPa) for i in range(len(test_vp)): self.assertTrue((self.vp[i]-test_vp[i]) < 0.1*u.kPa, msg= "Failure on {}.calc_vp({:3.1}) == {:3.1} (got {:3.1})".format(method, self.temp[i],self.vp[i],test_vp[i]))
def test_blackbody_maximum_agrees_with_wien(self, temp): '''Check the maximum of emission against Wien's law for photon rate''' emissivity = SpectralElement(Empirical1D, points=[1, 20], lookup_table=[1., 1.]) flux = surf_utils.make_emission_from_emissivity(temp, emissivity) dlam = 0.1 wave = np.arange(3, 20, dlam) * u.um wavemax = wave[np.argmax(flux(wave))] if isinstance(temp, u.Quantity): temp = temp.to(u.Kelvin, equivalencies=u.temperature()).value wienmax = 3669.7 * u.um / temp assert np.abs(wavemax - wienmax.to(u.um)) < dlam * u.um
def blackbody_nu(in_x, temperature): """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`. .. note:: Use `numpy.errstate` to suppress Numpy warnings, if desired. .. warning:: Output values might contain ``nan`` and ``inf``. Parameters in_x : number, array-like, or `~astropy.units.Quantity` Frequency, wavelength, or wave number. If not a Quantity, it is assumed to be in Hz. temperature : number, array-like, or `~astropy.units.Quantity` Blackbody temperature. If not a Quantity, it is assumed to be in Kelvin. Returns flux : `~astropy.units.Quantity` Blackbody monochromatic flux in :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`. Raises ValueError Invalid temperature. ZeroDivisionError Wavelength is zero (when converting to frequency). """ FNU = u.erg / (u.cm**2 * u.s * u.Hz) FLAM = u.erg / (u.cm**2 * u.s * u.AA) # Convert to units for calculations, also force double precision with u.add_enabled_equivalencies(u.spectral() + u.temperature()): freq = u.Quantity(in_x, u.Hz, dtype=np.float64) temp = u.Quantity(temperature, u.K, dtype=np.float64) log_boltz = const.h * freq / (const.k_B * temp) boltzm1 = np.expm1(log_boltz) # Calculate blackbody flux bb_nu = (2.0 * const.h * freq**3 / (const.c**2 * boltzm1)) flux = bb_nu.to(FNU, u.spectral_density(freq)) return flux / u.sr # Add per steradian to output flux unit
def calc_vp(self, temp) : """Implements: A * 10^( B * temp / (C + temp)) Parameters ---------- temp : array : units = degC Returns ------- c : array : units = Pa """ temp = temp.to(u.deg_C, equivalencies=u.temperature()) return self._A * (10 ** ((self._B * temp) / (self._C + temp)))
def calc_vp(self, temp): """Implements: A * 10^( B * temp / (C + temp)) Parameters ---------- temp : array : units = degC Returns ------- c : array : units = Pa """ temp = temp.to(u.deg_C, equivalencies=u.temperature()) return self._A * (10**((self._B * temp) / (self._C + temp)))
def test_returned_bb_curve_is_scaled_to_per_arcsec2(self): n = 11 sr2arcsec = u.sr.to(u.arcsec ** 2) wave = np.logspace(-1, 3, n) * u.um temp = (0 * u.deg_C).to(u.Kelvin, equivalencies=u.temperature()) srf = opt_surf.SpectralSurface(wavelength=wave, transmission=np.zeros(n), temperature=temp) emission_raw = SourceSpectrum(BlackBody1D, temperature=temp) assert isinstance(srf.emission, SourceSpectrum) assert np.allclose(emission_raw(wave) / sr2arcsec, srf.emission(wave))
def export(self, packetdata, exportstate, *, descr=False): val = '' convparam = getattr(packetdata, self.name) if convparam: if isinstance(convparam, EngineeringParameter): val = convparam.engineering elif isinstance(convparam, CompressedParameter): val = convparam.decompressed if isinstance(val, np.ndarray) and val.size > 1: # idx = self.order-convparam.order-1 idx = exportstate[self.name] exportstate[self.name] += 1 val = val[0][idx] if len(val.shape) > 1 else val[idx] if self.name == 'NIX00445': val = SCETime(coarse=self.value, fine=getattr(packetdata, "NIX00446", Parameter('NIX00446', 0, None)).value)\ .to_datetime().isoformat(timespec='milliseconds') elif self.name == 'NIX00402': if self.value > 2 ** 32 - 1: coarse = self.value >> 16 fine = self.value & (1 << 16) - 1 else: coarse = self.value fine = 0 val = SCETime(coarse, fine).to_datetime().isoformat(timespec='milliseconds') elif self.name == 'NIXD0003': val = round(self.value / 2.5, 3) if isinstance(convparam, EngineeringParameter): # undo °C to K if convparam.unit == 'degC': val = val.to('deg_C', equivalencies=u.temperature()) val = (val.value[0].round(3) if hasattr(val.value, "__len__") else round(val.value, 3)) if hasattr(val, "value") else str(val) if isinstance(val, np.ndarray): val = val[0] res = [self.name, self.value, val, [c.export(packetdata, exportstate, descr=descr) for c in self.children]] if descr: res.insert(1, self.idb_info.PCF_DESCR) return res
def evaluate(self, x, temperature, bolometric_flux): """Evaluate the model. Parameters ---------- x : float, `~numpy.ndarray`, or `~astropy.units.Quantity` Frequency at which to compute the blackbody. If no units are given, this defaults to Hz. temperature : float, `~numpy.ndarray`, or `~astropy.units.Quantity` Temperature of the blackbody. If no units are given, this defaults to Kelvin. bolometric_flux : float, `~numpy.ndarray`, or `~astropy.units.Quantity` Desired integral for the blackbody. Returns ------- y : number or ndarray Blackbody spectrum. The units are determined from the units of ``bolometric_flux``. """ # We need to make sure that we attach units to the temperature if it # doesn't have any units. We do this because even though blackbody_nu # can take temperature values without units, the / temperature ** 4 # factor needs units to be defined. if isinstance(temperature, u.Quantity): temperature = temperature.to(u.K, equivalencies=u.temperature()) else: temperature = u.Quantity(temperature, u.K) # We normalize the returned blackbody so that the integral would be # unity, and we then multiply by the bolometric flux. A normalized # blackbody has f_nu = pi * B_nu / (sigma * T^4), which is what we # calculate here. We convert to 1/Hz to make sure the units are # simplified as much as possible, then we multiply by the bolometric # flux to get the normalization right. fnu = ((np.pi * u.sr * blackbody_nu(x, temperature) / const.sigma_sb / temperature ** 4).to(1 / u.Hz) * bolometric_flux) # If the bolometric_flux parameter has no unit, we should drop the /Hz # and return a unitless value. This occurs for instance during fitting, # since we drop the units temporarily. if hasattr(bolometric_flux, 'unit'): return fnu else: return fnu.value
def eqmc(Temp, RH): """Calculate the equilibrium moisture content. Parameters ---------- Temp : array : degF RH : array : pct Returns ------- eqmc : array : pct This function does not maintain state between calls, so it does not need to be inside a class. EMC equations are presented in Appendix C of [1], as equations C-1, C-2, and C-3. Note that the RH ranges which select which equation to use have been fixed so they are not overlapping. We require that RH and Temp are both scalars or are both arrays of the same shape. We do not permit the case where one is a scalar and the other is an array. [1] Bradshaw, Larry S., John E. Deeming, Robert E. Burgan, and Jack D. Cohen. 1984. The 1978 National Fire-Danger Rating System: Technical Documentation. http://www.treesearch.fs.fed.us/pubs/29615. """ if (Temp.unit != iu.deg_F): Temp = Temp.to(iu.deg_F, u.temperature()) if RH.isscalar: # convert to an array of 1 RH = u.Quantity([RH]) Temp = u.Quantity([Temp]) case_c3 = np.where(RH > 50 * u.pct) case_c2 = np.where(np.logical_and(RH > 10 * u.pct, RH <= 50 * u.pct)) case_c1 = np.where(RH <= 10 * u.pct) retval = RH.copy() retval[case_c3] = ( 21.0606 * u.pct + (0.005565 * 1 / u.pct) * RH[case_c3]**2 - ((0.00035 * 1 / iu.deg_F) * RH[case_c3] * Temp[case_c3]) - 0.483199 * RH[case_c3]) retval[case_c2] = (2.22749 * u.pct + 0.160107 * RH[case_c2] - (0.014784 * u.pct / iu.deg_F) * Temp[case_c2]) retval[case_c1] = (0.03229 * u.pct + 0.281073 * RH[case_c1] - (0.000578 * 1 / iu.deg_F) * RH[case_c1] * Temp[case_c1]) return retval
def test_temperature(): from astropy.units.imperial import deg_F, deg_R t_k = 0 * u.K assert_allclose(t_k.to_value(u.deg_C, u.temperature()), -273.15) assert_allclose(t_k.to_value(deg_F, u.temperature()), -459.67) t_k = 20 * u.K assert_allclose(t_k.to_value(deg_R, u.temperature()), 36.0) t_k = 20 * deg_R assert_allclose(t_k.to_value(u.K, u.temperature()), 11.11, atol=0.01) t_k = 20 * deg_F assert_allclose(t_k.to_value(deg_R, u.temperature()), 479.67) t_k = 20 * deg_R assert_allclose(t_k.to_value(deg_F, u.temperature()), -439.67) t_k = 20 * u.deg_C assert_allclose(t_k.to_value(deg_R, u.temperature()), 527.67) t_k = 20 * deg_R assert_allclose(t_k.to_value(u.deg_C, u.temperature()), -262.039, atol=0.01)
def test_kelvin(self): """check to ensure that we can calculate vp using Kelvin temps""" for method in satvp.vp_calcs.keys(): calc = satvp.vp_calcs[method] # only reason to explicitly convert to kPa is to ensure the precision # of the comparison is expressed in kPa. test_vp = calc.calc_vp( self.temp.to(u.K, equivalencies=u.temperature())).to(u.kPa) for i in range(len(test_vp)): self.assertTrue( (self.vp[i] - test_vp[i]) < 0.1 * u.kPa, msg="Failure on {}.calc_vp({:3.1}) == {:3.1} (got {:3.1})". format(method, self.temp[i], self.vp[i], test_vp[i]))
def calc_vp(self, temp): """Implements: A * e^( B * temp / (C + temp)) Parameters ---------- temp : array : units = degC Returns ------- c : array : units = Pa """ # explicit conversion is necessary because units library # doesn't handle automatic conversion between temperature # units. temp = temp.to(u.deg_C, equivalencies=u.temperature()) return self._A * np.exp((self._B * temp) / (self._C + temp))
def eqmc (Temp,RH): """Calculate the equilibrium moisture content. Parameters ---------- Temp : array : degF RH : array : pct Returns ------- eqmc : array : pct This function does not maintain state between calls, so it does not need to be inside a class. EMC equations are presented in Appendix C of [1], as equations C-1, C-2, and C-3. Note that the RH ranges which select which equation to use have been fixed so they are not overlapping. We require that RH and Temp are both scalars or are both arrays of the same shape. We do not permit the case where one is a scalar and the other is an array. [1] Bradshaw, Larry S., John E. Deeming, Robert E. Burgan, and Jack D. Cohen. 1984. The 1978 National Fire-Danger Rating System: Technical Documentation. http://www.treesearch.fs.fed.us/pubs/29615. """ if (Temp.unit != iu.deg_F) : Temp = Temp.to(iu.deg_F, u.temperature()) if RH.isscalar : # convert to an array of 1 RH = u.Quantity([RH]) Temp = u.Quantity([Temp]) case_c3 = np.where(RH > 50*u.pct) case_c2 = np.where( np.logical_and(RH > 10*u.pct, RH<=50*u.pct)) case_c1 = np.where( RH <= 10*u.pct) retval = RH.copy() retval[case_c3] = (21.0606*u.pct + (0.005565 * 1/u.pct) * RH[case_c3]**2 - ((0.00035 * 1/iu.deg_F) * RH[case_c3] * Temp[case_c3]) - 0.483199 * RH[case_c3]) retval[case_c2] = (2.22749*u.pct + 0.160107 * RH[case_c2] - (0.014784 * u.pct/iu.deg_F) * Temp[case_c2]) retval[case_c1] = (0.03229*u.pct + 0.281073 * RH[case_c1] - (0.000578 * 1/iu.deg_F) * RH[case_c1] * Temp[case_c1]) return retval
def differential_p( zenith_distance, wl, wl_reference, temperature, pressure, relative_humidity, ): """Differential refraction as given by 1982PASP...94..715F """ zd = zenith_distance.to(u.rad).value p = pressure.to(u.Pascal).value / 133.322387415 t = temperature.to(u.deg_C, equivalencies=u.temperature()).value f = relative_humidity * p nl = 1 + 1e-6 * ref_index2(wl, p, t, f) n0 = 1 + 1e-6 * ref_index2(wl_reference, p, t, f) delt_r = (nl - n0) * math.tan(zd) return delt_r * u.rad
def extractTemperature(weather, useKelvin=False): """Thin wrapper to return the measured temperature from an observation. Parameters ---------- weather : `lsst.afw.coord.Weather` Class containing the measured temperature, pressure, and humidity at the observatory during an observation useKelvin : bool, optional Set to True to return the temperature in Kelvin instead of Celsius This is needed because Astropy can't easily convert between Kelvin and Celsius. Returns ------- temperature : `astropy.units.Quantity` The temperature in Celsius, unless `useKelvin` is set. """ temperature = weather.getAirTemperature()*units.Celsius if useKelvin: temperature = temperature.to(units.Kelvin, equivalencies=units.temperature()) return temperature
def oneten_ofdm(temp, rh, srad, fm_100) : """one and ten hour fuel moisture using the Oklahoma fire danger model Calculates the one and ten hour fuel moistures using the methodology in [2]. This method does not require knowledge of the "state of the weather", and may be easier to use with simulated met data. Parameters ---------- temp : array : deg_C 1.5 m temperature observation rh : array : pct 1.5 m relative humidity observation srad : array : W / m**2 1.5 m solar radiation observation from Li-Cor LI-200s pyranometer (bandpass: 400-1100nm) fm_100 : array : pct calculated 100-hr fuel moisture (dry basis) Returns ------- fm : array : pct tuple containing 1 and 10 hour % fuel moistures [2] Carlson, J. D., Robert E. Burgan, David M. Engle, and Justin R. Greenfield. 2002. “The Oklahoma Fire Danger Model: An Operational Tool for Mesoscale Fire Danger Rating in Oklahoma.” International Journal of Wildland Fire 11 (4): 183–91. """ temp = temp.to(u.deg_C, equivalencies=u.temperature()) fuel_temp = (srad/SOLAR_CONST)*(13.9 * u.deg_C ) + temp fuel_rh = (1 - 0.25*(srad/SOLAR_CONST))*rh fm_basis = 0.8 * eqmc(fuel_temp, fuel_rh) fm_10 = fm_basis + 0.2 * fm_100 fm_1 = fm_basis + 0.2 * fm_10 return (fm_1, fm_10)
def test_temperature(): from astropy.units.imperial import deg_F t_k = 0 * u.K assert_allclose(t_k.to_value(u.deg_C, u.temperature()), -273.15) assert_allclose(t_k.to_value(deg_F, u.temperature()), -459.67)
def create_observing_model(where, when, wavelength, temperature=15*u.deg_C, pressure=None, relative_humidity=0): """Create a model for observations through the atmosphere. This function encapsulates algorithms for the time-dependent transformation between sky coordinates and ALT-AZ through a specified atmosphere, and models the wavelength-dependent atmospheric refraction. The model returned by this function can be passed to :func:`sky_to_altaz` and :func:`altaz_to_sky` to transform sky coordinates such as RA,DEC to and from this model's ALT,AZ coordinate frame(s). The output shape resulting from using a model with :func:`sky_to_altaz` or :func:`altaz_to_sky` is determined by the usual `numpy broadcasting rules <http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html>`__ applied to all of the coordinates and observing model inputs, so this function can be used to tabulate an observing model on a user-specified grid covering location x time x wavelength x temperature x pressure x humidity. For example, to model a grid of observing times and wavelengths: >>> where = observatories['KPNO'] >>> when = astropy.time.Time([56382.9, 56383.1], format='mjd') >>> wlen = np.linspace(4000., 10000., 7) * u.Angstrom >>> obs_model = create_observing_model(where, when[:, np.newaxis], wlen) >>> sky_in = astropy.coordinates.ICRS(ra=45*u.deg, dec=45*u.deg) >>> sky_to_altaz(sky_in, obs_model).shape (2, 7) Parameters ---------- where : :class:`astropy.coordinates.EarthLocation` The location(s) on the earth where the sky is being observed. when : :class:`astropy.time.Time` The time(s) of the observations. wavelength : :class:`astropy.units.Quantity` The wavelength(s) of the observations with units of length. temperature : :class:`astropy.units.Quantity` The temperature(s) of the observations with temperature units. pressure : :class:`astropy.units.Quantity` The atmospheric pressure(s) of the observations with appropriate units. These should be pressures at the telescope, rather than adjusted to equivalent sea-level pressures. When ``None`` is specified, the pressure(s) will be estimated at the telescope elevation using a standard atmosphere model at the specified temperature(s). relative_humidity : :class:`float` or :class:`numpy.ndarray` Relative humidity (or humidities) of the observations. Value(s) should be in the range 0-1 and are dimensionless. Returns ------- :class:`astropy.coordinates.AltAz` An array of ALT-AZ coordinate frames with a shape given by :func:`np.broadcast(where, when, wavelength, temperature, pressure, relative_humidity) <numpy.broadcast>`. """ if not isinstance(relative_humidity, np.ndarray): relative_humidity = np.float(relative_humidity) if np.any((relative_humidity < 0) | (relative_humidity > 1)): raise ValueError('Values of relative_humidity must be 0-1.') # Convert temperature(s). T_in_C = temperature.to(u.deg_C, equivalencies=u.temperature()) # Estimate pressure(s) based on elevation, if necessary. # See https://en.wikipedia.org/wiki/Vertical_pressure_variation if pressure is None: h = where.height p0 = astropy.constants.atmosphere g0 = astropy.constants.g0 R = astropy.constants.R air_molar_mass = 0.0289644 * u.kg / u.mol T_in_K = temperature.to(u.K, equivalencies=u.temperature()) pressure = p0 * np.exp(-h * air_molar_mass * g0 / (R * T_in_K)) # Check that the input shapes are compatible for broadcasting to the output, # otherwise this will raise a ValueError. np.broadcast(where, when, wavelength, temperature, pressure, relative_humidity) # Initialize the altaz frames for each (time, wavelength, temperature, # pressure, relative_humidity). return astropy.coordinates.AltAz( location=where, obstime=when, obswl=wavelength, temperature=T_in_C, pressure=pressure, relative_humidity=relative_humidity)
def blackbody_nu(in_x, temperature): """Calculate blackbody flux per steradian, :math:`B_{\\nu}(T)`. .. note:: Use `numpy.errstate` to suppress Numpy warnings, if desired. .. warning:: Output values might contain ``nan`` and ``inf``. Parameters ---------- in_x : number, array-like, or `~astropy.units.Quantity` Frequency, wavelength, or wave number. If not a Quantity, it is assumed to be in Hz. temperature : number, array-like, or `~astropy.units.Quantity` Blackbody temperature. If not a Quantity, it is assumed to be in Kelvin. Returns ------- flux : `~astropy.units.Quantity` Blackbody monochromatic flux in :math:`erg \\; cm^{-2} s^{-1} Hz^{-1} sr^{-1}`. Raises ------ ValueError Invalid temperature. ZeroDivisionError Wavelength is zero (when converting to frequency). """ # Convert to units for calculations, also force double precision with u.add_enabled_equivalencies(u.spectral() + u.temperature()): freq = u.Quantity(in_x, u.Hz, dtype=np.float64) temp = u.Quantity(temperature, u.K, dtype=np.float64) # Check if input values are physically possible if np.any(temp < 0): raise ValueError('Temperature should be positive: {0}'.format(temp)) if not np.all(np.isfinite(freq)) or np.any(freq <= 0): warnings.warn('Input contains invalid wavelength/frequency value(s)', AstropyUserWarning) log_boltz = const.h * freq / (const.k_B * temp) boltzm1 = np.expm1(log_boltz) if _has_buggy_expm1: # Replace incorrect nan results with infs--any result of 'nan' is # incorrect unless the input (in log_boltz) happened to be nan to begin # with. (As noted in #4393 ideally this would be replaced by a version # of expm1 that doesn't have this bug, rather than fixing incorrect # results after the fact...) boltzm1_nans = np.isnan(boltzm1) if np.any(boltzm1_nans): if boltzm1.isscalar and not np.isnan(log_boltz): boltzm1 = np.inf else: boltzm1[np.where(~np.isnan(log_boltz) & boltzm1_nans)] = np.inf # Calculate blackbody flux bb_nu = (2.0 * const.h * freq ** 3 / (const.c ** 2 * boltzm1)) flux = bb_nu.to(FNU, u.spectral_density(freq)) return flux / u.sr # Add per steradian to output flux unit
def calc_i_tmin(tmin) : tmin = tmin.to(u.deg_C, equivalencies=u.temperature()) return __xf_tmin.scale(tmin)
#-------------------------- print("---------------------Fetching Data of Entered Planet----------------------") print("--------------------------------------------------------------------------") print("Selected Planet is " + x) print("Albedo of " + x + " is " + str(a)) print("Distance of " + x + " from sun is " + str(d)) print("--------That's it what we need to calculate equilibrium temperature-------") print("--------------------------------------------------------------------------") #Calculation of Equilibrium Temperature of any planet,... #... considering it has no atmosphere. t_p = tem.temp(x) t_p_c = t_p.to(u.deg_C, equivalencies=u.temperature()) print("----------------------Equilibrium Temperature-----------------------------") print("--------------------------------------------------------------------------") print("Equilibrium Temperature of " + x + " is " + str(t_p) + " (" + str(t_p_c) + " )") print("--------------------------------------------------------------------------") #Calculating Greenhouse Temperature of any planet t_g = tem.temp_gh(x) t_g_c = t_g.to(u.deg_C, equivalencies=u.temperature()) print("--------------------------------------------------------------------------") print("Greenhouse temperature of " + x + " is " + str(t_g)+ " (" + str(t_g_c) + " )") print("--------------------------------------------------------------------------") r1 = np.linspace(0,20000,10000)*u.m