Skip to content

Commit

Permalink
Added a configuration parser, and converted dsd moments and radar mom…
Browse files Browse the repository at this point in the history
…ents to use the new meta data fields (josephhardinee#38)
  • Loading branch information
josephhardinee authored Sep 22, 2016
1 parent e5ae077 commit a40f923
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 43 deletions.
2 changes: 1 addition & 1 deletion description.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
PyDisdrometer is a Python package to process disdrometer files. It currently is capable of reading several different types of disdrometers and calculating both important moment parameters, as well as radar derived parameters. It currently supports OTT Parsivel disdrometers and Joss Waldvogel Disdrometers. It is currently in alpha so functionality is limited but being expanded quickly.

Author: Joseph C. Hardin
Author: Joseph C. Hardin, Nick Guy
57 changes: 15 additions & 42 deletions pydisdrometer/DropSizeDistribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from . import DSR
from .utility import dielectric

from .utility import configuration
SPEED_OF_LIGHT=299792458

class DropSizeDistribution(object):
Expand Down Expand Up @@ -57,51 +57,30 @@ class DropSizeDistribution(object):
'''

def __init__(self, reader, time_start = None, location=None,):
def __init__(self, reader, time_start = None, location=None):
'''Initializer for the DropSizeDistribution class.
The DropSizeDistribution class holds dsd's returned from the various
readers in the io module.
Parameters
----------
# time: array_like
# An array of times corresponding to the time each dsd was sampled in minutes relative to time_start.
# Nd : 2d Array
# A list of drop size distributions
# spread: array_like
# Array giving the bin spread size for each size bin of the
# disdrometer.
# velocity: optional, array_like
# Terminal Fall Velocity for each size bin. This is based on the
# disdrometer assumptions.
# Z: optional, array_like
# The equivalent reflectivity factory from the disdrometer. Often
# taken as D**6.
# num_particles: optional, array_like
# Number of measured particles for each time instant.
# bin_edges: optional, array_like
# N+1 sized array of the boundaries of each size bin. For 30 bins
# for instance, there will be 31 different bin boundaries.
# diameter: optional, array_like
# The center size for each dsd bin.
reader: object
Object returned by package readers.
time_start: datetime
Recording Start time.
location: tuple
(Latitude, Longitude) pair in decimal format.
scattering_temp: optional, string
Scattering temperature string. One of ("0C","10C","20C").
Defaults to "10C"
Returns
-------
dsd: `DropSizeDistribution` instance
Drop Size Distribution instance.
'''

self.config = configuration.Configuration()

self.time = reader.time
self.Nd = reader.fields['Nd']
self.spread = reader.spread
Expand Down Expand Up @@ -210,16 +189,15 @@ def calculate_radar_parameters(self, dsr_func = DSR.bc, scatter_time_range = Non
for t in range(self.scatter_start_time, self.scatter_end_time):
self.fields['Kdp']['data'][t] = radar.Kdp(self.scatterer)
self.fields['Ai']['data'][t] = radar.Ai(self.scatterer)
self.fields['Ad']['data'][t] = radar.Ai(self.scatterer) -radar.Ai(self.scatterer, h_pol=False)
self.fields['Adr']['data'][t] = radar.Ai(self.scatterer) -radar.Ai(self.scatterer, h_pol=False)

def _setup_empty_fields(self, ):
def _setup_empty_fields(self ):
''' Preallocate arrays of zeros for the radar moments
'''
self.fields['Zh'] = {'data': np.ma.zeros(self.numt)}
self.fields['Zdr'] = {'data': np.ma.zeros(self.numt)}
self.fields['Kdp'] = {'data': np.ma.zeros(self.numt)}
self.fields['Ai'] = {'data': np.ma.zeros(self.numt)}
self.fields['Ad'] = {'data': np.ma.zeros(self.numt)}
params_list = ['Zh', 'Zdr', 'Kdp', 'Ai', 'Adr']

for param in params_list:
self.fields[param] = self.config.fill_in_metadata(param, np.ma.zeros(self.numt))

def _setup_scattering(self, wavelength, dsr_func):
''' Internal Function to create scattering tables.
Expand Down Expand Up @@ -292,15 +270,10 @@ def calculate_dsd_parameterization(self, method='bringi'):
'''

self.fields['Nt'] = {'data': np.ma.zeros(self.numt)}
self.fields['W'] = {'data': np.ma.zeros(self.numt)}
self.fields['D0'] = {'data': np.ma.zeros(self.numt)}
self.fields['Nw'] = {'data': np.ma.zeros(self.numt)}
self.fields['Dmax'] = {'data': np.ma.zeros(self.numt)}
self.fields['Dm'] = {'data': np.ma.zeros(self.numt)}
self.fields['Nw'] = {'data': np.ma.zeros(self.numt)}
self.fields['N0'] = {'data': np.ma.zeros(self.numt)}
self.fields['mu'] = {'data': np.ma.zeros(self.numt)}
params_list = ['D0', 'Dmax', 'Dm', 'Nt', 'Nw', 'N0', 'W', 'mu']

for param in params_list:
self.fields[param] = self.config.fill_in_metadata(param, np.ma.zeros(self.numt))

rho_w = 1e-03 # grams per mm cubed Density of Water
vol_constant = np.pi / 6.0 * rho_w
Expand Down
17 changes: 17 additions & 0 deletions pydisdrometer/tests/testConfiguration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-

import numpy as np
import unittest
from ..utility import configuration

from .. import DropSizeDistribution

class testConfiguration(unittest.TestCase):
''' Unit tests for Configuration Class'''

def setUp(self):
self.config = configuration.Configuration()

def test_config_loads_and_has_keys(self):
self.assertIsNotNone(self.config)
self.assertTrue(len(self.config.metadata.keys()) > 0 )
32 changes: 32 additions & 0 deletions pydisdrometer/utility/configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import json
from copy import copy
import os



class Configuration(object):
''' Class to store PyDisdrometer configuration options
Attributes:
-----------
'''
config_dir = os.path.dirname(os.path.abspath(__file__))
metadata_config_file = os.path.join(config_dir, 'metadata.json')

def __init__(self):
self.metadata = self.load_metadata_config()

def load_metadata_config(self):
''' Load the metadata configuration file and return the dictionary'''
return json.load(open(self.metadata_config_file))


def fill_in_metadata(self, field, data):
metadata = self.metadata[field].copy()
metadata['data'] = copy(data)
return metadata




88 changes: 88 additions & 0 deletions pydisdrometer/utility/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{
"D0":
{
"standard_name": "median_drop_diameter",
"units": "mm",
"long_name": "Median Drop Diameter"
},
"Dmax":
{
"standard_name": "maximum_drop_diameter",
"units": "mm",
"long_name" :"Maximum Drop Diameter"
},
"Dm":
{
"standard_name": "mean_drop_diameter",
"units": "mm",
"long_name" :"Mean Drop Diameter"
},
"Nw":
{
"standard_name": "normalized_intercept_parameter",
"units": "?",
"long_name" :"Normalized Intercept Parameter of a Normalized Gaussian Distribution"
},
"Nt":
{
"standard_name": "total_droplet_concentration",
"units": "m^-1",
"long_name" :"Total Droplet Concentration"
},
"N0":
{
"standard_name": "intercept_parameter",
"units": "?",
"long_name" :"Intercept Parameter of Modeled Drop Size Distribution"
},
"W":
{
"standard_name": "water_mass",
"units": "g/m^3",
"long_name" :"Water Mass of Drop Size Distribution"
},
"mu":
{
"standard_name": "shape_parameter",
"units": " ",
"long_name" :"Shape Parameter of Modeled Drop Size Distribution"
},
"rain_rate":
{
"standard_name": "rain_rate",
"units": "mm/h",
"long_name" :"Instantaneous Rainfall Rate of Water Flux"
},
"Zh":
{
"standard_name": "horizontal_reflectivity",
"units": "dBZ",
"long_name" :"Estimated Horizontal Radar Reflectivity from Drop Size Distribution"
},
"Zdr":
{
"standard_name": "differential_reflectivity",
"units": "dBZ",
"long_name" :"Estimated Differential Radar Reflectivity (H, V) from Drop Size Distribution"
},
"Kdp":
{
"standard_name": "specific_differential_phase",
"units": "deg",
"long_name" :"Specific Differential Phase from Drop Size Distribution"
},
"Ai":
{
"standard_name": "specific_attenuation",
"units": "dB/km",
"long_name": "Specific Attenuation"
},
"Adr":
{
"standard_name": "specific_differential_attenuation",
"units": "dB/km",
"long_name": "Specific Differential Attenuation"
}
}


0 comments on commit a40f923

Please sign in to comment.