Skip to content

Atmo

Atmo

A base class for creating Atmo. Atmospheric conditions and density calculations

Attributes:

Name Type Description
altitude Distance

Altitude relative to sea level

pressure Pressure

Atmospheric pressure

temperature Temperature

Atmospheric temperature

humidity float

Atmospheric humidity

powder_temp Temperature

Custom temperature of powder different to atmospheric. Uses together with Ammo.use_powder_sensitivity

density_ratio float

Density ratio

mach Velocity

Velocity instance that keeps velocity in mach for current atmosphere

Parameters:

Name Type Description Default
altitude Optional[Union[float, Distance]]

Altitude relative to sea level

None
pressure Optional[Union[float, Pressure]]

Atmospheric pressure

None
temperature Optional[Union[float, Temperature]]

Atmospheric temperature

None
humidity float

Atmospheric humidity in percents

0.0
powder_t Optional[Union[float, Temperature]]

Custom temperature of powder different to atmospheric. Uses together with Ammo.use_powder_sensitivity

None
Example

This is how you can create an Atmo

from py_ballisticcalc import Atmo
wind = Wind(
    altitude=Unit.Meter(100),
    pressure=Unit.hPa(1000),
    temperature=Unit.Celsius(20),
    humidity=50,
    powder_t=1.23
)

Source code in py_ballisticcalc\conditions.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
def __init__(self,
             altitude: Optional[Union[float, Distance]] = None,
             pressure: Optional[Union[float, Pressure]] = None,
             temperature: Optional[Union[float, Temperature]] = None,
             humidity: float = 0.0,
             powder_t: Optional[Union[float, Temperature]] = None):
    """
    Create a new Atmo instance with given parameters

    Args:
        altitude: Altitude relative to sea level
        pressure: Atmospheric pressure
        temperature: Atmospheric temperature
        humidity: Atmospheric humidity in percents
        powder_t: Custom temperature of powder different to atmospheric.
            Uses together with Ammo.use_powder_sensitivity

    Example:
        This is how you can create an Atmo
        ```python
        from py_ballisticcalc import Atmo
        wind = Wind(
            altitude=Unit.Meter(100),
            pressure=Unit.hPa(1000),
            temperature=Unit.Celsius(20),
            humidity=50,
            powder_t=1.23
        )
        ```
    """

    self.humidity = humidity or 0.0
    if self.humidity > 1:
        self.humidity = humidity / 100.0
    if not 0 <= self.humidity <= 1:
        self.humidity = 0.0

    self.altitude = PreferredUnits.distance(altitude or 0)
    self.pressure = PreferredUnits.pressure(pressure or Atmo.standard_pressure(self.altitude))
    self.temperature = PreferredUnits.temperature(temperature or Atmo.standard_temperature(self.altitude))
    # ensure that if powder_temperature are not provided we use atmospheric temperature
    self.powder_temp = PreferredUnits.temperature(powder_t or self.temperature)

    self._t0 = self.temperature >> Temperature.Fahrenheit
    self._p0 = self.pressure >> Pressure.InHg
    self._a0 = self.altitude >> Distance.Foot
    self._ta = self._a0 * cLapseRateImperial + cStandardTemperatureF
    self.density_ratio = self.calculate_density(self._t0, self._p0) / cStandardDensity
    self._mach1 = Atmo.machF(self._t0)
    self.mach = Velocity.FPS(self._mach1)

altitude instance-attribute

altitude: Distance = distance(altitude or 0)

pressure instance-attribute

pressure: Pressure = pressure(pressure or standard_pressure(altitude))

temperature instance-attribute

temperature: Temperature = temperature(temperature or standard_temperature(altitude))

humidity instance-attribute

humidity: float = humidity or 0.0

powder_temp instance-attribute

powder_temp: Temperature = temperature(powder_t or temperature)

density_ratio instance-attribute

density_ratio: float = calculate_density(_t0, _p0) / cStandardDensity

mach instance-attribute

mach: Velocity = FPS(_mach1)

standard_temperature staticmethod

standard_temperature(altitude: Distance) -> Temperature

Returns:

Type Description
Temperature

ICAO standard temperature for altitude

Source code in py_ballisticcalc\conditions.py
 99
100
101
102
103
104
105
106
@staticmethod
def standard_temperature(altitude: Distance) -> Temperature:
    """
    Returns:
        ICAO standard temperature for altitude
    """
    return Temperature.Fahrenheit(cStandardTemperatureF
                                  + (altitude >> Distance.Foot) * cLapseRateImperial)

standard_pressure staticmethod

standard_pressure(altitude: Distance) -> Pressure

Returns:

Type Description
Pressure

ICAO standard pressure for altitude

Source code in py_ballisticcalc\conditions.py
108
109
110
111
112
113
114
115
116
117
@staticmethod
def standard_pressure(altitude: Distance) -> Pressure:
    """
    Returns:
        ICAO standard pressure for altitude
    """
    return Pressure.InHg(0.02953
                         * math.pow(3.73145 - 2.56555e-05 * (altitude >> Distance.Foot),
                                    cPressureExponent)
                         )

standard staticmethod

standard(altitude: Union[float, Distance] = 0, temperature: Optional[Temperature] = None) -> Atmo

Parameters:

Name Type Description Default
altitude Union[float, Distance]

relative to sea level

0
temperature Optional[Temperature]

Temperature instance

None

Returns: Atmo instance. Creates standard ICAO atmosphere at given altitude. If temperature not specified uses standard temperature.

Source code in py_ballisticcalc\conditions.py
123
124
125
126
127
128
129
130
131
132
133
@staticmethod
def standard(altitude: Union[float, Distance] = 0, temperature: Optional[Temperature] = None) -> 'Atmo':
    """
    Args:
        altitude: relative to sea level
        temperature: Temperature instance
    Returns:
        Atmo instance. Creates standard ICAO atmosphere at given altitude.
        If temperature not specified uses standard temperature.
    """
    return Atmo.icao(altitude, temperature)

icao staticmethod

icao(altitude: Union[float, Distance] = 0, temperature: Optional[Temperature] = None) -> Atmo

Parameters:

Name Type Description Default
altitude Union[float, Distance]

relative to sea level

0
temperature Optional[Temperature]

Temperature instance

None

Returns: Atmo instance. Creates standard ICAO atmosphere at given altitude. If temperature not specified uses standard temperature.

Source code in py_ballisticcalc\conditions.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
@staticmethod
def icao(altitude: Union[float, Distance] = 0, temperature: Optional[Temperature] = None) -> 'Atmo':
    """
    Args:
        altitude: relative to sea level
        temperature: Temperature instance
    Returns:
        Atmo instance. Creates standard ICAO atmosphere at given altitude.
        If temperature not specified uses standard temperature.
    """
    altitude = PreferredUnits.distance(altitude)
    if temperature is None:
        temperature = Atmo.standard_temperature(altitude)
    pressure = Atmo.standard_pressure(altitude)

    return Atmo(
        altitude >> PreferredUnits.distance,
        pressure >> PreferredUnits.pressure,
        temperature >> PreferredUnits.temperature,
        cStandardHumidity
    )

machF staticmethod

machF(fahrenheit: float) -> float

Parameters:

Name Type Description Default
fahrenheit float

Fahrenheit temperature

required

Returns: Mach 1 in fps for Fahrenheit temperature

Source code in py_ballisticcalc\conditions.py
157
158
159
160
161
162
163
164
165
166
167
168
169
170
@staticmethod
def machF(fahrenheit: float) -> float:
    """
    Args:
        fahrenheit: Fahrenheit temperature
    Returns:
        Mach 1 in fps for Fahrenheit temperature
    """
    if fahrenheit < -cDegreesFtoR:
        fahrenheit = -cDegreesFtoR
        warnings.warn(f"Invalid temperature: {fahrenheit}°F. Adjusted to absolute zero "
                      f"It must be >= {-cDegreesFtoR} to avoid a domain error."
                      f"redefine 'cDegreesFtoR' constant to increase it", RuntimeWarning)
    return math.sqrt(fahrenheit + cDegreesFtoR) * cSpeedOfSoundImperial

machC staticmethod

machC(celsius: float) -> float

Parameters:

Name Type Description Default
celsius float

Celsius temperature

required

Returns: Mach 1 in m/s for Celsius temperature

Source code in py_ballisticcalc\conditions.py
172
173
174
175
176
177
178
179
180
181
182
183
184
185
@staticmethod
def machC(celsius: float) -> float:
    """
    Args:
        celsius: Celsius temperature
    Returns:
        Mach 1 in m/s for Celsius temperature
    """
    if celsius < -cDegreesCtoK:
        celsius = -cDegreesCtoK
        warnings.warn(f"Invalid temperature: {celsius}°C. Adjusted to absolute zero "
                      f"It must be >= {-cDegreesCtoK} to avoid a domain error."
                      f"redefine 'cDegreesCtoK' constant to increase it", RuntimeWarning)
    return math.sqrt(1 + celsius / cDegreesCtoK) * cSpeedOfSoundMetric

air_density staticmethod

air_density(t: Temperature, p: Pressure, humidity: float) -> float

Wiki: Density_of_air

Parameters:

Name Type Description Default
t Temperature

Temperature instance

required
p Pressure

Pressure instance

required
humidity float

Humidity instance

required

Returns:

Type Description
float

Density in Imperial units (lb/ft^3)

Source code in py_ballisticcalc\conditions.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
@staticmethod
def air_density(t: Temperature, p: Pressure, humidity: float) -> float:
    """
    Wiki: [Density_of_air](https://en.wikipedia.org/wiki/Density_of_air#Humid_air)

    Args:
        t: Temperature instance
        p: Pressure instance
        humidity: Humidity instance

    Returns:
        Density in Imperial units (lb/ft^3)
    """
    tC = t >> Temperature.Celsius
    pM = (p >> Pressure.hPa) * 100  # Pressure in Pascals
    # Tetens approximation to saturation vapor pressure:
    psat = 6.1078 * math.pow(10, 17.27 * tC / (tC + 237.3))
    pv = humidity * psat  # Pressure of water vapor in Pascals
    pd = pM - pv  # Partial pressure of dry air in Pascals
    # Density in metric units kg/m^3
    density = (pd * 0.0289652 + pv * 0.018016) / (8.31446 * (tC + cDegreesCtoK))
    return density / cDensityImperialToMetric

density_metric property

density_metric: float

Returns:

Type Description
float

density in kg/m^3

density_imperial property

density_imperial: float

Returns:

Type Description
float

density in lb/ft^3

temperature_at_altitude

temperature_at_altitude(altitude: float) -> float

Interpolated temperature at altitude Args: altitude: ASL in ft Returns: temperature in °F

Source code in py_ballisticcalc\conditions.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
def temperature_at_altitude(self, altitude: float) -> float:
    """
    Interpolated temperature at altitude
    Args:
         altitude: ASL in ft
    Returns:
        temperature in °F
    """
    t = (altitude - self._a0) * cLapseRateImperial + self._t0
    if t < cLowestTempF:
        t = cLowestTempF
        warnings.warn(f"Reached minimum temperature limit. Adjusted to {cLowestTempF}°F "
                      "redefine 'cLowestTempF' constant to increase it ", RuntimeWarning)
    return t

calculate_density

calculate_density(t: float, p: float) -> float

Parameters:

Name Type Description Default
t float

temperature in °F

required
p float

pressure in inHg

required

Returns: density with specified atmosphere

Source code in py_ballisticcalc\conditions.py
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
def calculate_density(self, t: float, p: float) -> float:
    """
    Args:
        t: temperature in °F
        p: pressure in inHg
    Returns:
        density with specified atmosphere
    """
    if t > 0:
        et0 = cA0 + t * (cA1 + t * (cA2 + t * (cA3 + t * cA4)))
        et = cA5 * self.humidity * et0
        hc = (p - 0.3783 * et) / cStandardPressure
    else:
        hc = 1.0

    density = cStandardDensity * (
            (cStandardTemperatureF + cDegreesFtoR) / (t + cDegreesFtoR)
    ) * hc
    return density

get_density_factor_and_mach_for_altitude

get_density_factor_and_mach_for_altitude(altitude: float) -> Tuple[float, float]

Parameters:

Name Type Description Default
altitude float

ASL in units of feet

required

Returns: density ratio and Mach 1 (fps) for the specified altitude

Source code in py_ballisticcalc\conditions.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
def get_density_factor_and_mach_for_altitude(self, altitude: float) -> Tuple[float, float]:
    """
    Args:
        altitude: ASL in units of feet
    Returns:
        density ratio and Mach 1 (fps) for the specified altitude
    """
    # Within 30 ft of initial altitude use initial values
    if math.fabs(self._a0 - altitude) < 30:
        density_ratio = self.density_ratio
        mach = self._mach1
    else:
        # https://en.wikipedia.org/wiki/Density_of_air#Exponential_approximation
        density_ratio = math.exp(-altitude / 34112.0)
        t = self.temperature_at_altitude(altitude)
        mach = Atmo.machF(t)
    return density_ratio, mach