def checkDataIntegrity(self): if not qc_tools.isHGHTValid(self.hght): qc_tools.raiseError("Invalid height data. Data has repeat height values or height does not increase as pressure decreases.", qc_tools.DataQualityException) if not qc_tools.isTMPCValid(self.tmpc): qc_tools.raiseError("Invalid temperature data. Profile contains a temperature value < -273.15 Celsius.", qc_tools.DataQualityException) if not qc_tools.isDWPCValid(self.dwpc): qc_tools.raiseError("Invalid dewpoint data. Profile contains a dewpoint value < -273.15 Celsius.", qc_tools.DataQualityException) if not qc_tools.isWSPDValid(self.wspd): qc_tools.raiseError("Invalid wind speed data. Profile contains a wind speed value < 0 knots.", qc_tools.DataQualityException) if not qc_tools.isWDIRValid(self.wdir): qc_tools.raiseError("Invalid wind direction data. Profile contains a wind direction < 0 degrees or >= 360 degrees.", qc_tools.DataQualityException)
def __init__(self, **kwargs): ''' Create the sounding data object Parameters ---------- Mandatory Keywords pres : array_like The pressure values (Hectopaschals) hght : array_like The corresponding height values (Meters) tmpc : array_like The corresponding temperature values (Celsius) dwpc : array_like The corresponding dewpoint temperature values (Celsius) Optional Keyword Pairs (must use one or the other) wdir : array_like The direction from which the wind is blowing in meteorological degrees wspd : array_like The speed of the wind OR u : array_like The U-component of the direction from which the wind is blowing v : array_like The V-component of the direction from which the wind is blowing. Optional Keywords missing : number (default: sharppy.sharptab.constants.MISSING) The value of the missing flag location : string (default: None) The 3 character station identifier or 4 character WMO station ID for radiosonde locations. Used for the PWV database. strictQC : boolean A flag that indicates whether or not the strict quality control routines should be run on the profile upon construction. Returns ------- prof: Profile object ''' super(BasicProfile, self).__init__(**kwargs) strictQC = kwargs.get('strictQC', True) assert len(self.pres) == len(self.hght) == len(self.tmpc) == len(self.dwpc),\ "Length of pres, hght, tmpc, or dwpc arrays passed to constructor are not the same." ## did the user provide the wind in vector form? if self.wdir is not None: assert len(self.wdir) == len(self.wspd) == len( self.pres ), "Length of wdir and wspd arrays passed to constructor are not the same length as the pres array." self.wdir[self.wdir == self.missing] = ma.masked self.wspd[self.wspd == self.missing] = ma.masked self.wdir[self.wspd.mask] = ma.masked self.wspd[self.wdir.mask] = ma.masked self.u, self.v = utils.vec2comp(self.wdir, self.wspd) ## did the user provide the wind in u,v form? elif self.u is not None: assert len(self.u) == len(self.v) == len( self.pres ), "Length of u and v arrays passed to constructor are not the same length as the pres array." self.u[self.u == self.missing] = ma.masked self.v[self.v == self.missing] = ma.masked self.u[self.v.mask] = ma.masked self.v[self.u.mask] = ma.masked self.wdir, self.wspd = utils.comp2vec(self.u, self.v) ## check if any standard deviation data was supplied if self.tmp_stdev is not None: self.dew_stdev[self.dew_stdev == self.missing] = ma.masked self.tmp_stdev[self.tmp_stdev == self.missing] = ma.masked self.dew_stdev.set_fill_value(self.missing) self.tmp_stdev.set_fill_value(self.missing) if self.omeg is not None: ## get the omega data and turn into arrays assert len(self.omeg) == len( self.pres ), "Length of omeg array passed to constructor is not the same length as the pres array." self.omeg[self.omeg == self.missing] = ma.masked else: self.omeg = ma.masked_all(len(self.hght)) # QC Checks on the arrays passed to the constructor. qc_tools.areProfileArrayLengthEqual(self) ## mask the missing values self.pres[self.pres == self.missing] = ma.masked self.hght[self.hght == self.missing] = ma.masked self.tmpc[self.tmpc == self.missing] = ma.masked self.dwpc[self.dwpc == self.missing] = ma.masked #if not qc_tools.isPRESValid(self.pres): ## qc_tools.raiseError("Incorrect order of pressure array (or repeat values) or pressure array is of length <= 1.", ValueError) if not qc_tools.isHGHTValid(self.hght) and strictQC: qc_tools.raiseError( "Incorrect order of height (or repeat values) array or height array is of length <= 1.", ValueError) if not qc_tools.isTMPCValid(self.tmpc): qc_tools.raiseError( "Invalid temperature array. Array contains a value < -273.15 Celsius.", ValueError) if not qc_tools.isDWPCValid(self.dwpc): qc_tools.raiseError( "Invalid dewpoint array. Array contains a value < -273.15 Celsius.", ValueError) if not qc_tools.isWSPDValid(self.wspd) and strictQC: qc_tools.raiseError( "Invalid wind speed array. Array contains a value < 0 knots.", ValueError) if not qc_tools.isWDIRValid(self.wdir) and strictQC: qc_tools.raiseError( "Invalid wind direction array. Array contains a value < 0 degrees or value > 360 degrees.", ValueError) self.logp = np.log10(self.pres.copy()) self.vtmp = thermo.virtemp(self.pres, self.tmpc, self.dwpc) idx = np.ma.where(self.pres > 0)[0] self.vtmp[self.dwpc.mask[idx]] = self.tmpc[ self.dwpc.mask[idx]] # Masking any virtual temperature ## get the index of the top and bottom of the profile self.sfc = self.get_sfc() self.top = self.get_top() ## generate the wetbulb profile self.wetbulb = self.get_wetbulb_profile() ## generate theta-e profile self.thetae = self.get_thetae_profile()
''' Create the Sounding (Profile) Object '''
def __init__(self, **kwargs): ''' Create the sounding data object Parameters ---------- Mandatory Keywords pres : array_like The pressure values (Hectopaschals) hght : array_like The corresponding height values (Meters) tmpc : array_like The corresponding temperature values (Celsius) dwpc : array_like The corresponding dewpoint temperature values (Celsius) Optional Keyword Pairs (must use one or the other) wdir : array_like The direction from which the wind is blowing in meteorological degrees wspd : array_like The speed of the wind OR u : array_like The U-component of the direction from which the wind is blowing v : array_like The V-component of the direction from which the wind is blowing. Optional Keywords missing : number (default: sharppy.sharptab.constants.MISSING) The value of the missing flag location : string (default: None) The 3 character station identifier or 4 character WMO station ID for radiosonde locations. Used for the PWV database. strictQC : boolean A flag that indicates whether or not the strict quality control routines should be run on the profile upon construction. Returns ------- prof: Profile object ''' super(BasicProfile, self).__init__(**kwargs) strictQC = kwargs.get('strictQC', True) assert len(self.pres) == len(self.hght) == len(self.tmpc) == len(self.dwpc),\ "Length of pres, hght, tmpc, or dwpc arrays passed to constructor are not the same." ## did the user provide the wind in vector form? if self.wdir is not None: assert len(self.wdir) == len(self.wspd) == len(self.pres), "Length of wdir and wspd arrays passed to constructor are not the same length as the pres array." self.wdir[self.wdir == self.missing] = ma.masked self.wspd[self.wspd == self.missing] = ma.masked self.wdir[self.wspd.mask] = ma.masked self.wspd[self.wdir.mask] = ma.masked self.u, self.v = utils.vec2comp(self.wdir, self.wspd) ## did the user provide the wind in u,v form? elif self.u is not None: assert len(self.u) == len(self.v) == len(self.pres), "Length of u and v arrays passed to constructor are not the same length as the pres array." self.u[self.u == self.missing] = ma.masked self.v[self.v == self.missing] = ma.masked self.u[self.v.mask] = ma.masked self.v[self.u.mask] = ma.masked self.wdir, self.wspd = utils.comp2vec(self.u, self.v) ## check if any standard deviation data was supplied if self.tmp_stdev is not None: self.dew_stdev[self.dew_stdev == self.missing] = ma.masked self.tmp_stdev[self.tmp_stdev == self.missing] = ma.masked self.dew_stdev.set_fill_value(self.missing) self.tmp_stdev.set_fill_value(self.missing) if self.omeg is not None: ## get the omega data and turn into arrays assert len(self.omeg) == len(self.pres), "Length of omeg array passed to constructor is not the same length as the pres array." self.omeg[self.omeg == self.missing] = ma.masked else: self.omeg = ma.masked_all(len(self.hght)) # QC Checks on the arrays passed to the constructor. qc_tools.areProfileArrayLengthEqual(self) ## mask the missing values self.pres[self.pres == self.missing] = ma.masked self.hght[self.hght == self.missing] = ma.masked self.tmpc[self.tmpc == self.missing] = ma.masked self.dwpc[self.dwpc == self.missing] = ma.masked #if not qc_tools.isPRESValid(self.pres): ## qc_tools.raiseError("Incorrect order of pressure array (or repeat values) or pressure array is of length <= 1.", ValueError) if not qc_tools.isHGHTValid(self.hght) and strictQC: qc_tools.raiseError("Incorrect order of height (or repeat values) array or height array is of length <= 1.", ValueError) if not qc_tools.isTMPCValid(self.tmpc): qc_tools.raiseError("Invalid temperature array. Array contains a value < 273.15 Celsius.", ValueError) if not qc_tools.isDWPCValid(self.dwpc): qc_tools.raiseError("Invalid dewpoint array. Array contains a value < 273.15 Celsius.", ValueError) if not qc_tools.isWSPDValid(self.wspd) and strictQC: qc_tools.raiseError("Invalid wind speed array. Array contains a value < 0 knots.", ValueError) if not qc_tools.isWDIRValid(self.wdir) and strictQC: qc_tools.raiseError("Invalid wind direction array. Array contains a value < 0 degrees or value >= 360 degrees.", ValueError) self.logp = np.log10(self.pres.copy()) self.vtmp = thermo.virtemp( self.pres, self.tmpc, self.dwpc ) idx = np.ma.where(self.pres > 0)[0] self.vtmp[self.dwpc.mask[idx]] = self.tmpc[self.dwpc.mask[idx]] # Masking any virtual temperature ## get the index of the top and bottom of the profile self.sfc = self.get_sfc() self.top = self.get_top() ## generate the wetbulb profile self.wetbulb = self.get_wetbulb_profile() ## generate theta-e profile self.thetae = self.get_thetae_profile()