python-awips/_sources/examples/generated/Model_Sounding_Data.rst.txt
2022-08-22 19:36:49 +00:00

1427 lines
27 KiB
ReStructuredText
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

===================
Model Sounding Data
===================
`Notebook <http://nbviewer.ipython.org/github/Unidata/python-awips/blob/master/examples/notebooks/Model_Sounding_Data.ipynb>`_
Python-AWIPS Tutorial Notebook
--------------
Objectives
==========
- Use python-awips to connect to an edex server
- Define and filter data request for model sounding data
- Create vertical profiles from GFS BUFR products
- Use MetPy to create
`SkewT <https://unidata.github.io/MetPy/latest/api/generated/metpy.plots.SkewT.html>`__
and
`Hodograph <https://unidata.github.io/MetPy/latest/api/generated/metpy.plots.Hodograph.html>`__
plots
--------------
Table of Contents
-----------------
| `1
Imports <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#imports>`__\
| `2 EDEX
Connection <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#edex-connection>`__\
| `3 Setting
Location <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#setting-location>`__\
|     `3.1 Available Location
Names <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#available-location-names>`__\
|     `3.2 Setting the Location
Name <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#setting-the-location-name>`__\
| `4 Filtering by
Time <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#filtering-by-time>`__\
| `5 Get the
Data! <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#get-the-data>`__\
| `6 Use the
Data! <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#use-the-data>`__\
|     `6.1 Prepare Data
Objects <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#prepare-data-objects>`__\
|     `6.2 Calculate Dewpoint from Specific
Humidity <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#calculate-dewpoint-from-specific-humidity>`__\
|         `6.2.1 Method
1 <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#method-1>`__\
|         `6.2.2 Method
2 <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#method-2>`__\
|         `6.2.3 Method
3 <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#method-3>`__\
| `7 Plot the
Data! <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#plot-the-data>`__\
| `8 See
Also <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#see-also>`__\
|     `8.1 Related
Notebooks <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#related-notebooks>`__\
|     `8.2 Additional
Documentation <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html#additional-documentation>`__\
1 Imports
---------
The imports below are used throughout the notebook. Note the first
import is coming directly from python-awips and allows us to connect to
an EDEX server. The subsequent imports are for data manipulation and
visualization.
.. code:: ipython3
from awips.dataaccess import DataAccessLayer
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from math import exp, log
import numpy as np
from metpy.calc import dewpoint, vapor_pressure, wind_speed, wind_direction
from metpy.plots import SkewT, Hodograph
from metpy.units import units
`Top <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html>`__
--------------
2 EDEX Connection
-----------------
First we establish a connection to Unidatas public EDEX server. With
that connection made, we can create a `new data request
object <http://unidata.github.io/python-awips/api/IDataRequest.html>`__
and set the data type to **modelsounding**, and define additional
parameters and an identifier on the request.
.. code:: ipython3
DataAccessLayer.changeEDEXHost("edex-cloud.unidata.ucar.edu")
request = DataAccessLayer.newDataRequest("modelsounding")
forecastModel = "GFS"
request.addIdentifier("reportType", forecastModel)
request.setParameters("pressure","temperature","specHum","uComp","vComp")
`Top <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html>`__
--------------
3 Setting Location
------------------
3.1 Available Location Names
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When working with a new data type, it is often useful to investigate all
available options for a particular setting. Shown below is how to see
all available location names for a data request with type
``modelsounding`` and ``reportType`` identifier of ``GFS``. This step is
not necessary if you already know exactly what the location name(s)
youre interested in is.
.. code:: ipython3
locations = DataAccessLayer.getAvailableLocationNames(request)
locations.sort()
list(locations)
.. parsed-literal::
['',
'1V4',
'3J2',
'4BL',
'4BQ',
'4HV',
'4OM',
'5AF',
'5AG',
'5SZ',
'6RO',
'8V7',
'9B6',
'A#2',
'A#3',
'A#4',
'A#5',
'A#6',
'A#7',
'A#8',
'A#9',
'A#A',
'A#B',
'ABL',
'ADM',
'AFA',
'AGR',
'AHN',
'AIA',
'AIH',
'AJO',
'ANJ',
'APX',
'AQQ',
'ATH',
'ATL1',
'ATL2',
'ATL3',
'ATL4',
'ATLH',
'AWH',
'AWR',
'B#1',
'B#2',
'B#3',
'B#4',
'B#5',
'B#6',
'B#7',
'B#8',
'B#9',
'B#A',
'B#B',
'B#C',
'B#D',
'B#E',
'B#F',
'B#G',
'B#H',
'B#J',
'B#K',
'B#L',
'B#M',
'B#N',
'B#O',
'B#P',
'B#Q',
'B#S',
'BAB',
'BDG',
'BDP',
'BFL',
'BGTL',
'BH1',
'BH2',
'BH3',
'BH4',
'BH5',
'BHK',
'BID',
'BIR',
'BLS',
'BLU',
'BMX',
'BNA',
'BOD',
'BRA',
'BTL',
'BVR',
'C01',
'C02',
'C03',
'C04',
'C06',
'C07',
'C08',
'C09',
'C10',
'C11',
'C12',
'C13',
'C14',
'C17',
'C18',
'C19',
'C20',
'C21',
'C22',
'C23',
'C24',
'C25',
'C27',
'C28',
'C30',
'C31',
'C32',
'C33',
'C34',
'C35',
'C36',
'C7H',
'CAI',
'CAN',
'CBE',
'CBN',
'CHE',
'CKN',
'CLD',
'CLE',
'CLN',
'COL1',
'COL2',
'COL3',
'COL4',
'COT',
'CQV',
'CRL',
'CRR',
'CTY',
'CVM',
'CVS',
'CWEU',
'CWFN',
'CWKX',
'CWLB',
'CWLO',
'CWLT',
'CWLW',
'CWMW',
'CWOS',
'CWPH',
'CWQG',
'CWSA',
'CWSE',
'CWZB',
'CWZC',
'CWZV',
'CYAH',
'CYAW',
'CYBK',
'CYBU',
'CYCB',
'CYCG',
'CYCX',
'CYDA',
'CYEG',
'CYEV',
'CYFB',
'CYFO',
'CYFS',
'CYGQ',
'CYHM',
'CYHZ',
'CYJT',
'CYLH',
'CYLJ',
'CYMD',
'CYMO',
'CYMT',
'CYMX',
'CYOC',
'CYOW',
'CYPA',
'CYPE',
'CYPL',
'CYPQ',
'CYQA',
'CYQD',
'CYQG',
'CYQH',
'CYQI',
'CYQK',
'CYQQ',
'CYQR',
'CYQT',
'CYQX',
'CYQY',
'CYRB',
'CYSM',
'CYSY',
'CYTH',
'CYTL',
'CYTS',
'CYUL',
'CYUX',
'CYVO',
'CYVP',
'CYVQ',
'CYVR',
'CYVV',
'CYWA',
'CYWG',
'CYWO',
'CYXC',
'CYXE',
'CYXH',
'CYXS',
'CYXU',
'CYXX',
'CYXY',
'CYXZ',
'CYYB',
'CYYC',
'CYYE',
'CYYJ',
'CYYQ',
'CYYR',
'CYYT',
'CYYZ',
'CYZF',
'CYZS',
'CYZT',
'CYZV',
'DEN',
'DOV',
'DPG',
'DSC',
'DSD',
'DTX',
'DVN',
'DYS',
'E28',
'E74',
'EAT',
'EAX',
'EDW',
'EFL',
'EMP',
'END',
'ENL',
'ESTC',
'FCS',
'FDR',
'FFC',
'FHU',
'FLG',
'FLP',
'FPK',
'FRI',
'FSI',
'FTR',
'FWD',
'G#1',
'G#2',
'G#3',
'G#4',
'G#5',
'G#6',
'G#7',
'G#8',
'G#9',
'G#A',
'G#B',
'G#C',
'G#D',
'G#E',
'G#F',
'G#G',
'G001',
'G003',
'G004',
'G005',
'G007',
'G009',
'GDP',
'GDV',
'GLRY',
'GMX1',
'GNB',
'GNC',
'GRF',
'GTB',
'GTP',
'GVL',
'GVS',
'GYX',
'H02',
'HAY',
'HGR',
'HMN',
'HOM',
'HOO',
'HSI',
'HYR',
'HYS',
'ICC',
'IGM',
'ILN',
'ILS',
'ILX',
'IMT',
'INK',
'IPX',
'JACK',
'JDN',
'K40B',
'K9V9',
'KABE',
'KABI',
'KABQ',
'KABR',
'KABY',
'KACK',
'KACT',
'KACV',
'KACY',
'KAGC',
'KAGS',
'KAHN',
'KAK',
'KALB',
'KALI',
'KALO',
'KALS',
'KALW',
'KAMA',
'KAN',
'KANB',
'KAND',
'KAOO',
'KAPA',
'KAPN',
'KART',
'KASE',
'KAST',
'KATL',
'KATY',
'KAUG',
'KAUS',
'KAUW',
'KAVL',
'KAVP',
'KAXN',
'KAYS',
'KAZO',
'KBAF',
'KBCE',
'KBDE',
'KBDL',
'KBDR',
'KBED',
'KBFD',
'KBFF',
'KBFI',
'KBFL',
'KBGM',
'KBGR',
'KBHB',
'KBHM',
'KBIH',
'KBIL',
'KBIS',
'KBJC',
'KBJI',
'KBKE',
'KBKW',
'KBLF',
'KBLH',
'KBLI',
'KBML',
'KBNA',
'KBNO',
'KBNV',
'KBOI',
'KBOS',
'KBPT',
'KBQK',
'KBRD',
'KBRL',
'KBRO',
'KBTL',
'KBTM',
'KBTR',
'KBTV',
'KBUF',
'KBUR',
'KBVI',
'KBVX',
'KBVY',
'KBWG',
'KBWI',
'KBYI',
'KBZN',
'KCAE',
'KCAK',
'KCAR',
'KCDC',
'KCDR',
'KCDS',
'KCEC',
'KCEF',
'KCGI',
'KCGX',
'KCHA',
'KCHH',
'KCHO',
'KCHS',
'KCID',
'KCIU',
'KCKB',
'KCKL',
'KCLE',
'KCLL',
'KCLM',
'KCLT',
'KCMH',
'KCMI',
'KCMX',
'KCNM',
'KCNU',
'KCOD',
'KCOE',
'KCON',
'KCOS',
'KCOU',
'KCPR',
'KCRE',
'KCRP',
'KCRQ',
'KCRW',
'KCSG',
'KCSV',
'KCTB',
'KCVG',
'KCWA',
'KCYS',
'KDAB',
'KDAG',
'KDAL',
'KDAN',
'KDAY',
'KDBQ',
'KDCA',
'KDDC',
'KDEC',
'KDEN',
'KDET',
'KDFW',
'KDHN',
'KDHT',
'KDIK',
'KDLH',
'KDLS',
'KDMN',
'KDPA',
'KDRA',
'KDRO',
'KDRT',
'KDSM',
'KDTW',
'KDUG',
'KDUJ',
'KEAT',
'KEAU',
'KECG',
'KEED',
'KEGE',
'KEKN',
'KEKO',
'KEL',
'KELD',
'KELM',
'KELO',
'KELP',
'KELY',
'KENV',
'KEPH',
'KEPO',
'KEPZ',
'KERI',
'KESF',
'KEUG',
'KEVV',
'KEWB',
'KEWN',
'KEWR',
'KEYW',
'KFAM',
'KFAR',
'KFAT',
'KFAY',
'KFCA',
'KFDY',
'KFKL',
'KFLG',
'KFLL',
'KFLO',
'KFMN',
'KFMY',
'KFNT',
'KFOE',
'KFPR',
'KFRM',
'KFSD',
'KFSM',
'KFTW',
'KFTY',
'KFVE',
'KFVX',
'KFWA',
'KFXE',
'KFYV',
'KGAG',
'KGCC',
'KGCK',
'KGCN',
'KGEG',
'KGFK',
'KGFL',
'KGGG',
'KGGW',
'KGJT',
'KGLD',
'KGLH',
'KGLS',
'KGMU',
'KGNR',
'KGNV',
'KGON',
'KGPT',
'KGRB',
'KGRI',
'KGRR',
'KGSO',
'KGSP',
'KGTF',
'KGUC',
'KGUP',
'KGWO',
'KGYY',
'KGZH',
'KHAT',
'KHBR',
'KHDN',
'KHIB',
'KHIO',
'KHKY',
'KHLG',
'KHLN',
'KHOB',
'KHON',
'KHOT',
'KHOU',
'KHPN',
'KHQM',
'KHRL',
'KHRO',
'KHSV',
'KHTH',
'KHTS',
'KHUF',
'KHUL',
'KHUT',
'KHVN',
'KHVR',
'KHYA',
'KIAD',
'KIAG',
'KIAH',
'KICT',
'KIDA',
'KIL',
'KILG',
'KILM',
'KIND',
'KINK',
'KINL',
'KINT',
'KINW',
'KIPL',
'KIPT',
'KISN',
'KISP',
'KITH',
'KIWD',
'KJAC',
'KJAN',
'KJAX',
'KJBR',
'KJFK',
'KJHW',
'KJKL',
'KJLN',
'KJMS',
'KJST',
'KJXN',
'KKL',
'KLAF',
'KLAN',
'KLAR',
'KLAS',
'KLAX',
'KLBB',
'KLBE',
'KLBF',
'KLCB',
'KLCH',
'KLEB',
'KLEX',
'KLFK',
'KLFT',
'KLGA',
'KLGB',
'KLGU',
'KLIT',
'KLMT',
'KLND',
'KLNK',
'KLOL',
'KLOZ',
'KLRD',
'KLSE',
'KLUK',
'KLVS',
'KLWB',
'KLWM',
'KLWS',
'KLWT',
'KLYH',
'KLZK',
'KMAF',
'KMBS',
'KMCB',
'KMCE',
'KMCI',
'KMCN',
'KMCO',
'KMCW',
'KMDN',
'KMDT',
'KMDW',
'KMEI',
'KMEM',
'KMFD',
'KMFE',
'KMFR',
'KMGM',
'KMGW',
'KMHE',
'KMHK',
'KMHT',
'KMHX',
'KMIA',
'KMIV',
'KMKC',
'KMKE',
'KMKG',
'KMKL',
'KMLB',
'KMLC',
'KMLI',
'KMLS',
'KMLT',
'KMLU',
'KMMU',
'KMOB',
'KMOT',
'KMPV',
'KMQT',
'KMRB',
'KMRY',
'KMSL',
'KMSN',
'KMSO',
'KMSP',
'KMSS',
'KMSY',
'KMTJ',
'KMTN',
'KMWH',
'KMYR',
'KNA',
'KNEW',
'KNL',
'KNSI',
'KOAK',
'KOFK',
'KOGD',
'KOKC',
'KOLM',
'KOMA',
'KONT',
'KOPF',
'KOQU',
'KORD',
'KORF',
'KORH',
'KOSH',
'KOTH',
'KOTM',
'KP11',
'KP38',
'KPAE',
'KPAH',
'KPBF',
'KPBI',
'KPDK',
'KPDT',
'KPDX',
'KPFN',
'KPGA',
'KPHF',
'KPHL',
'KPHN',
'KPHX',
'KPIA',
'KPIB',
'KPIE',
'KPIH',
'KPIR',
'KPIT',
'KPKB',
'KPLN',
'KPMD',
'KPNC',
'KPNE',
'KPNS',
'KPOU',
'KPQI',
'KPRB',
'KPRC',
'KPSC',
'KPSM',
'KPSP',
'KPTK',
'KPUB',
'KPVD',
'KPVU',
'KPWM',
'KRAD',
'KRAP',
'KRBL',
'KRDD',
'KRDG',
'KRDM',
'KRDU',
'KRFD',
'KRIC',
'KRIW',
'KRKD',
'KRKS',
'KRNO',
'KRNT',
'KROA',
'KROC',
'KROW',
'KRSL',
'KRST',
'KRSW',
'KRUM',
'KRWF',
'KRWI',
'KRWL',
'KSAC',
'KSAF',
'KSAN',
'KSAT',
'KSAV',
'KSBA',
'KSBN',
'KSBP',
'KSBY',
'KSCH',
'KSCK',
'KSDF',
'KSDM',
'KSDY',
'KSEA',
'KSEP',
'KSFF',
'KSFO',
'KSGF',
'KSGU',
'KSHR',
'KSHV',
'KSJC',
'KSJT',
'KSLC',
'KSLE',
'KSLK',
'KSLN',
'KSMF',
'KSMX',
'KSNA',
'KSNS',
'KSPI',
'KSPS',
'KSRQ',
'KSSI',
'KSTJ',
'KSTL',
'KSTP',
'KSTS',
'KSUN',
'KSUS',
'KSUX',
'KSVE',
'KSWF',
'KSYR',
'KTCC',
'KTCL',
'KTCS',
'KTEB',
'KTIW',
'KTLH',
'KTMB',
'KTOL',
'KTOP',
'KTPA',
'KTPH',
'KTRI',
'KTRK',
'KTRM',
'KTTD',
'KTTN',
'KTUL',
'KTUP',
'KTUS',
'KTVC',
'KTVL',
'KTWF',
'KTXK',
'KTYR',
'KTYS',
'KUCA',
'KUIN',
'KUKI',
'KUNV',
'KVCT',
'KVEL',
'KVLD',
'KVNY',
'KVRB',
'KWJF',
'KWMC',
'KWRL',
'KWYS',
'KY22',
'KY26',
'KYKM',
'KYKN',
'KYNG',
'KYUM',
'KZZV',
'LAA',
'LAP',
'LBY',
'LDL',
'LHX',
'LIC',
'LOR',
'LRR',
'LSF',
'LUS',
'LVM',
'LW1',
'MAC',
'MAX',
'MAZ',
'MDPC',
'MDPP',
'MDSD',
'MDST',
'MGFL',
'MGGT',
'MGHT',
'MGPB',
'MGSJ',
'MHAM',
'MHCA',
'MHCH',
'MHLC',
'MHLE',
'MHLM',
'MHNJ',
'MHPL',
'MHRO',
'MHSR',
'MHTE',
'MHTG',
'MHYR',
'MIB',
'MIE',
'MKJP',
'MKJS',
'MLD',
'MMAA',
'MMAS',
'MMBT',
'MMCE',
'MMCL',
'MMCN',
'MMCS',
'MMCU',
'MMCV',
'MMCZ',
'MMDO',
'MMGL',
'MMGM',
'MMHO',
'MMLP',
'MMMA',
'MMMD',
'MMML',
'MMMM',
'MMMT',
'MMMX',
'MMMY',
'MMMZ',
'MMNL',
'MMPR',
'MMRX',
'MMSD',
'MMSP',
'MMTC',
'MMTJ',
'MMTM',
'MMTO',
'MMTP',
'MMUN',
'MMVR',
'MMZC',
'MMZH',
'MMZO',
'MNMG',
'MNPC',
'MOR',
'MPBO',
'MPCH',
'MPDA',
'MPMG',
'MPSA',
'MPTO',
'MPX',
'MRCH',
'MRF',
'MRLB',
'MRLM',
'MROC',
'MRPV',
'MRS',
'MSAC',
'MSLP',
'MSSS',
'MTCH',
'MTL',
'MTPP',
'MTV',
'MTY',
'MUBA',
'MUBY',
'MUCA',
'MUCL',
'MUCM',
'MUCU',
'MUGM',
'MUGT',
'MUHA',
'MUMO',
'MUMZ',
'MUNG',
'MUVR',
'MUVT',
'MWCR',
'MYBS',
'MYEG',
'MYGF',
'MYGW',
'MYL',
'MYNN',
'MZBZ',
'MZT',
'NCK',
'NGX',
'NHK',
'NID',
'NKX',
'NOA',
'NRU',
'NTD',
...]
3.2 Setting the Location Name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this case were setting the location name to ``KFRM`` which is the
Municipal Airport in Fairmont, Minnesota.
.. code:: ipython3
request.setLocationNames("KFRM")
`Top <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html>`__
--------------
4 Filtering by Time
-------------------
Models produce many different time variants during their runs, so lets
limit the data to the most recent time and forecast run.
.. code:: ipython3
cycles = DataAccessLayer.getAvailableTimes(request, True)
times = DataAccessLayer.getAvailableTimes(request)
try:
fcstRun = DataAccessLayer.getForecastRun(cycles[-1], times)
list(fcstRun)
response = DataAccessLayer.getGeometryData(request,[fcstRun[0]])
except:
print('No times available')
exit
`Top <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html>`__
--------------
5 Get the Data!
---------------
Here we can now request our data response from the EDEX server with our
defined time filter. Printing out some data about the response verifies
we received the data we were interested in.
.. code:: ipython3
obj = response[0]
print("parms = " + str(obj.getParameters()))
print("site = " + str(obj.getLocationName()))
print("geom = " + str(obj.getGeometry()))
print("datetime = " + str(obj.getDataTime()))
print("reftime = " + str(obj.getDataTime().getRefTime()))
print("fcstHour = " + str(obj.getDataTime().getFcstTime()))
print("period = " + str(obj.getDataTime().getValidPeriod()))
.. parsed-literal::
parms = ['temperature', 'pressure', 'vComp', 'uComp', 'specHum']
site = KFRM
geom = POINT (-94.41999816894531 43.65000152587891)
datetime = 2022-08-19 12:00:00
reftime = Aug 19 22 12:00:00 GMT
fcstHour = 0
period = (Aug 19 22 12:00:00 , Aug 19 22 12:00:00 )
`Top <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html>`__
--------------
6 Use the Data!
---------------
Since we filtered on time, and requested the data in the previous cell,
we now have a ``response`` object we can work with.
6.1 Prepare Data Objects
~~~~~~~~~~~~~~~~~~~~~~~~
Here we construct arrays for each parameter to plot (temperature,
pressure, moisture (spec. humidity), wind components, and cloud cover).
We have two sets of arrays for temperature and pressure, where the
second set only has values as long as the specific humidity is not zero.
That is because we are going to do some calculations with specific
humidity, temperature, and pressure and we need all those arrays to be
the same length, and for the specific humidty to not equal zero.
.. code:: ipython3
# Create new arrays to populate from our response objects
tmp,prs,sh,prs2,tmp2 = np.array([]),np.array([]),np.array([]),np.array([]),np.array([])
uc,vc = np.array([]),np.array([])
# Cycle through all response objects to populate new arrays
for ob in response:
tmp = np.append(tmp,ob.getNumber("temperature"))
prs = np.append(prs,ob.getNumber("pressure"))
uc = np.append(uc,ob.getNumber("uComp"))
vc = np.append(vc,ob.getNumber("vComp"))
# don't include data with 0 specific humidity
if(ob.getNumber("specHum")==0):
continue
sh = np.append(sh,ob.getNumber("specHum"))
prs2 = np.append(prs2,ob.getNumber("pressure"))
tmp2 = np.append(tmp2,ob.getNumber("temperature"))
6.2 Calculate Dewpoint from Specific Humidity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Because the modelsounding plugin does not return dewpoint values, we
must calculate the profile ourselves. Here are three examples of
dewpoint calculated from specific humidity, including a manual
calculation following NCEP AWIPS/NSHARP.
First, well set up variables that are used in all three methods (and
later in the notebook).
.. code:: ipython3
tfull = (tmp-273.15) * units.degC
t = (tmp2-273.15) * units.degC
pfull = prs/100 * units.mbar
p = prs2/100 * units.mbar
u,v = uc*1.94384,vc*1.94384 # m/s to knots
spd = wind_speed(u*units.knots, v*units.knots)
dir = wind_direction(u*units.knots, v*units.knots) * units.deg
6.2.1 Method 1
^^^^^^^^^^^^^^
Here well calculate the dewpoint using MetPy calculated mixing ratio
and the vapor pressure.
.. code:: ipython3
rmix = (sh/(1-sh)) *1000 * units('g/kg')
e = vapor_pressure(p, rmix)
td = dewpoint(e)
6.2.2 Method 2
^^^^^^^^^^^^^^
Here well calculate dewpoint using MetPy while assuming the mixing
ratio is equal to the specific humidity.
.. code:: ipython3
td2 = dewpoint(vapor_pressure(p, sh))
6.2.3 Method 3
^^^^^^^^^^^^^^
Here we use logic from the NCEP AWIPS soundingrequest plugin. This logic
was based on `GEMPAK and NSHARP
calculations <https://github.com/Unidata/awips2-ncep/blob/unidata_16.2.2/edex/gov.noaa.nws.ncep.edex.plugin.soundingrequest/src/gov/noaa/nws/ncep/edex/plugin/soundingrequest/handler/MergeSounding.java#L1783>`__.
.. code:: ipython3
# new arrays
ntmp = tmp2
# where p=pressure(pa), T=temp(C), T0=reference temp(273.16)
rh = 0.263*prs2*sh / (np.exp(17.67*ntmp/(ntmp+273.15-29.65)))
vaps = 6.112 * np.exp((17.67 * ntmp) / (ntmp + 243.5))
vapr = rh * vaps / 100
dwpc = np.array(243.5 * (np.log(6.112) - np.log(vapr)) / (np.log(vapr) - np.log(6.112) - 17.67)) * units.degC
`Top <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html>`__
--------------
7 Plot the Data!
----------------
Create and display SkewT and Hodograph plots using MetPy.
Since were displaying all three dewpoint plots, we also create a
“zoomed in” view to highlight the slight differences between the three
calculations.
.. code:: ipython3
# Create a new figure and define the size
fig = plt.figure(figsize=(12, 14))
# Create a skewT plot
skew = SkewT(fig)
# Plot the data
skew.plot(pfull, tfull, 'r', linewidth=2)
skew.plot(p, td, 'b', linewidth=2)
skew.plot(p, td2, 'y', linewidth=2)
skew.plot(p, dwpc, 'g', linewidth=2)
skew.plot_barbs(pfull, u, v)
# set the domain and range (these may need to be adjusted
# depending on the exact data for best viewing purposes)
skew.ax.set_ylim(1000, 100)
skew.ax.set_xlim(-70, 40)
# Add title to the plot
# format: "2022-08-18 18Z FH 0 | GFS KFRM (43.65,-94.42)"
datetime = str(ob.getDataTime())[0:-6]+"Z"
forecastHr = str(ob.getDataTime().getFcstTime())
site = ob.getLocationName()
lat = "{:.2f}".format(ob.getGeometry().y)
lon = "{:.2f}".format(ob.getGeometry().x)
coords = "(" + lat + ", " + lon +")"
title = datetime + " FH " + forecastHr + " | " + forecastModel + " " + site + " " + coords
plt.title(title)
# Create a secondary axes for the "zoomed in" view
zoom_ax = inset_axes(skew.ax, '35%', '35%', loc=3,
bbox_to_anchor=(.05, .05, 1, 1),
bbox_transform=skew.ax.transAxes)
# create a secondary plot for zoomed in section
fig2 = plt.figure()
skew2 = SkewT(fig2)
skew2.ax = zoom_ax
skew2.plot(p, td, 'b', linewidth=2, label='MetPy calculated mixing ratio')
skew2.plot(p, td2, 'y', linewidth=2, label='MetPy spec. hum = mixing ratio')
skew2.plot(p, dwpc, 'g', linewidth=2, label='GEMPAK legacy caluclation')
# create a legend to explain the three lines
skew2.ax.legend(loc=1)
# remove the axis title on the zoomed plot since they
# are redundant and just clutter the plot
skew2.ax.set_xlabel("")
skew2.ax.set_ylabel("")
# these exact bounds may need to change depending on
# the most recent data
skew2.ax.set_ylim(970, 900)
skew2.ax.set_xlim(11, 14)
# draw an indicator in the main plot of the "zoomed in" region
skew.ax.indicate_inset_zoom(zoom_ax, edgecolor="black")
# dispose of the second figure, since creating a new
# skewt in metpy automatically creates a new figure
# which is unnecessary in this case
plt.close(fig2)
# An example of a slanted line at constant T -- in this case the 0 isotherm
l = skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)
# Draw hodograph
ax_hod = inset_axes(skew.ax, '40%', '40%', loc=1)
h = Hodograph(ax_hod, component_range=spd.max()/units.knots)
h.add_grid(increment=20)
h.plot_colormapped(u, v, spd)
# Show the plot
plt.show()
.. image:: Model_Sounding_Data_files/Model_Sounding_Data_34_0.png
`Top <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html>`__
--------------
8 See Also
----------
8.1 Related Notebooks
~~~~~~~~~~~~~~~~~~~~~
- `Grid Levels and
Parameters <https://unidata.github.io/python-awips/examples/generated/Grid_Levels_and_Parameters.html>`__
- `Upper Air BUFR
Soundings <http://unidata.github.io/python-awips/examples/generated/Upper_Air_BUFR_Soundings.html>`__
- `Forecast Model Vertical
Sounding <http://unidata.github.io/python-awips/examples/generated/Forecast_Model_Vertical_Sounding.html>`__
8.2 Additional Documentation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**python-awips:**
- `awips.DataAccessLayer <http://unidata.github.io/python-awips/api/DataAccessLayer.html>`__
- `awips.PyGeometryData <http://unidata.github.io/python-awips/api/PyGeometryData.html>`__
**matplotlib:**
- `matplotlib.pyplot <https://matplotlib.org/3.3.3/api/_as_gen/matplotlib.pyplot.html>`__
- `metpy.skewt <https://unidata.github.io/MetPy/latest/api/generated/metpy.plots.SkewT.html>`__
`Top <https://unidata.github.io/python-awips/examples/generated/Model_Sounding_Data.html>`__
--------------