##// END OF EJS Templates
25/04/18
25/04/18

File last commit:

r1021:2aa9b10a9a70
r1156:b9e1884ee58d
Show More
jroIO_madrigal.py
243 lines | 7.4 KiB | text/x-python | PythonLexer
'''
Created on Aug 1, 2017
@author: Juan C. Espinoza
'''
import os
import sys
import time
import json
import datetime
import numpy
try:
import madrigal
import madrigal.cedar
except:
print 'You should install "madrigal library" module if you want to read/write Madrigal data'
from schainpy.model.proc.jroproc_base import Operation
from schainpy.model.data.jrodata import Parameters
MISSING = -32767
DEF_CATALOG = {
'principleInvestigator': 'Marco Milla',
'expPurpose': None,
'expMode': None,
'cycleTime': None,
'correlativeExp': None,
'sciRemarks': None,
'instRemarks': None
}
DEF_HEADER = {
'kindatDesc': None,
'analyst': 'Jicamarca User',
'comments': None,
'history': None
}
MNEMONICS = {
10: 'jro',
11: 'jbr',
840: 'jul',
13: 'jas',
1000: 'pbr',
1001: 'hbr',
1002: 'obr',
}
def load_json(obj):
'''
Parse json as string instead of unicode
'''
if isinstance(obj, str):
obj = json.loads(obj)
return {str(k): load_json(v) if isinstance(v, dict) else str(v) if isinstance(v, unicode) else v
for k, v in obj.items()}
class MAD2Writer(Operation):
def __init__(self, **kwargs):
Operation.__init__(self, **kwargs)
self.dataOut = Parameters()
self.path = None
self.dataOut = None
self.ext = '.dat'
return
def run(self, dataOut, path, oneDList, twoDParam='', twoDList='{}', metadata='{}', **kwargs):
'''
Inputs:
path - path where files will be created
oneDList - json of one-dimensional parameters in record where keys
are Madrigal codes (integers or mnemonics) and values the corresponding
dataOut attribute e.g: {
'gdlatr': 'lat',
'gdlonr': 'lon',
'gdlat2':'lat',
'glon2':'lon'}
twoDParam - independent parameter to get the number of rows e.g:
heighList
twoDList - json of two-dimensional parameters in record where keys
are Madrigal codes (integers or mnemonics) and values the corresponding
dataOut attribute if multidimensional array specify as tupple
('attr', pos) e.g: {
'gdalt': 'heightList',
'vn1p2': ('data_output', 0),
'vn2p2': ('data_output', 1),
'vn3': ('data_output', 2),
'snl': ('data_SNR', 'db')
}
metadata - json of madrigal metadata (kinst, kindat, catalog and header)
'''
if not self.isConfig:
self.setup(dataOut, path, oneDList, twoDParam, twoDList, metadata, **kwargs)
self.isConfig = True
self.putData()
return
def setup(self, dataOut, path, oneDList, twoDParam, twoDList, metadata, **kwargs):
'''
Configure Operation
'''
self.dataOut = dataOut
self.nmodes = self.dataOut.nmodes
self.path = path
self.blocks = kwargs.get('blocks', None)
self.counter = 0
self.oneDList = load_json(oneDList)
self.twoDList = load_json(twoDList)
self.twoDParam = twoDParam
meta = load_json(metadata)
self.kinst = meta.get('kinst')
self.kindat = meta.get('kindat')
self.catalog = meta.get('catalog', DEF_CATALOG)
self.header = meta.get('header', DEF_HEADER)
return
def setFile(self):
'''
Create new cedar file object
'''
self.mnemonic = MNEMONICS[self.kinst] #TODO get mnemonic from madrigal
date = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
filename = '%s%s_%s%s' % (self.mnemonic,
date.strftime('%Y%m%d_%H%M%S'),
self.dataOut.mode,
self.ext)
self.fullname = os.path.join(self.path, filename)
if os.path.isfile(self.fullname) :
print "Destination path '%s' already exists. Previous file deleted. " %self.fullname
os.remove(self.fullname)
try:
print '[Writing] creating file : %s' % (self.fullname)
self.cedarObj = madrigal.cedar.MadrigalCedarFile(self.fullname, True)
except ValueError, e:
print '[Error]: Impossible to create a cedar object with "madrigal.cedar.MadrigalCedarFile" '
return
return 1
def writeBlock(self):
'''
Add data records to cedar file taking data from oneDList and twoDList
attributes.
Allowed parameters in: parcodes.tab
'''
startTime = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
nrows = len(getattr(self.dataOut, self.twoDParam))
rec = madrigal.cedar.MadrigalDataRecord(
self.kinst,
self.kindat,
startTime.year,
startTime.month,
startTime.day,
startTime.hour,
startTime.minute,
startTime.second,
startTime.microsecond/10000,
endTime.year,
endTime.month,
endTime.day,
endTime.hour,
endTime.minute,
endTime.second,
endTime.microsecond/10000,
self.oneDList.keys(),
self.twoDList.keys(),
nrows
)
# Setting 1d values
for key in self.oneDList:
rec.set1D(key, getattr(self.dataOut, self.oneDList[key]))
# Setting 2d values
invalid = numpy.isnan(self.dataOut.data_output)
self.dataOut.data_output[invalid] = MISSING
out = {}
for key, value in self.twoDList.items():
if isinstance(value, str):
out[key] = getattr(self.dataOut, value)
elif isinstance(value, tuple):
attr, x = value
if isinstance(x, (int, float)):
out[key] = getattr(self.dataOut, attr)[int(x)]
elif x.lower()=='db':
tmp = getattr(self.dataOut, attr)
SNRavg = numpy.average(tmp, axis=0)
out[key] = 10*numpy.log10(SNRavg)
for n in range(nrows):
for key in out:
rec.set2D(key, n, out[key][n])
self.cedarObj.append(rec)
self.cedarObj.dump()
print '[Writing] Record No. {} (mode {}).'.format(
self.counter,
self.dataOut.mode
)
def setHeader(self):
'''
Create an add catalog and header to cedar file
'''
header = madrigal.cedar.CatalogHeaderCreator(self.fullname)
header.createCatalog(**self.catalog)
header.createHeader(**self.header)
header.write()
def putData(self):
if self.dataOut.flagNoData:
return 0
if self.counter == 0:
self.setFile()
if self.counter <= self.dataOut.nrecords:
self.writeBlock()
self.counter += 1
if self.counter == self.dataOut.nrecords or self.counter == self.blocks:
self.setHeader()
self.counter = 0