Commit 952ea954 authored by François Fortin's avatar François Fortin
Browse files

add vertical level to roadcast output

metro_data has been adapted to handle multi column data

new xml handler for list item.
parent de4ab480
......@@ -67,6 +67,21 @@ class Metro_data:
ex 'AT', 'FORECAST_TIME', etc.
Numpy are used to represent the matrix.
A column is identified by a name. But a name can reference
several real column in the matrix. The attribute lMatrix_col_usage
store the column index of each column name.
Mutli col can only be in extended data types.
This is how it work:
AT = 1 column
FORECAST_TIME = 1 column
TL = 4 column
self.lMatrix_col_name = ['AT', 'FORECAST_TIME', 'TL']
self.lMatrix_col_usage = [[0], [1], [2,3,4,5]]
It is possible to prevent modification of the data by using the read_only
functionnality provided by the class.
......@@ -201,9 +216,10 @@ class Metro_data:
npCol (numpy array): the array corresponding to this column.
"""
iCol = self.index_of_matrix_col(sCol_name)
# FFTODO set multi col
iCol = self.index_of_matrix_col(sCol_name)[0]
if not self.is_readonly():
if iCol > len(self.npMatrix[0,:]):
sOutOfBoundError = _("Array does not contain this indice: %d") \
......@@ -261,7 +277,14 @@ class Metro_data:
if not self.is_readonly():
if sCol_name not in self.lMatrix_col_name:
self.lMatrix_col_name.append(sCol_name)
if self.lMatrix_col_usage == []:
nextCol = 0
else:
nextCol = self.lMatrix_col_usage[-1][-1] + 1
self.lMatrix_col_usage.append(range(nextCol,nextCol+1))
self.lMatrix_ext_col_name.append(sCol_name)
# Append column in the matrix
self.npMatrix = self.__append_col_to_matrix(self.npMatrix,\
......@@ -276,6 +299,53 @@ class Metro_data:
MESSAGE_READONLY)
raise ERROR_METRO_DATA, MESSAGE_READONLY
def append_matrix_multiCol( self, sCol_name, lColOfList ):
"""
Name: append_matrix_col
Parameters: I sCol_name : column name
I npData_col : column to insert in the matrix.
Returns: 0 if success
Descriptions: Append a new column of data to the matrix. Matix column
will be accessible with the name specified by sCol_name.
Column will be treated as extended
"""
if not self.is_readonly():
if sCol_name not in self.lMatrix_col_name:
self.lMatrix_col_name.append(sCol_name)
if self.lMatrix_col_usage == []:
nextCol = 0
else:
nextCol = self.lMatrix_col_usage[-1][-1] + 1
nbCol = len(lColOfList[0])
self.lMatrix_col_usage.append(range(nextCol,nextCol+nbCol))
self.lMatrix_ext_col_name.append(sCol_name)
# Append column in the matrix
for i in range(0,nbCol):
colToInsert = []
for col in lColOfList:
colToInsert.append(col[i])
self.npMatrix = self.__append_col_to_matrix(self.npMatrix,\
colToInsert)
else:
sError = _("Cant append column '%s'.%s") % (sCol_name,
MESSAGE_COL_EXIST)
raise ERROR_METRO_DATA, sError
else:
metro_logger.print_message(metro_logger.LOGGER_MSG_DEBUG,
MESSAGE_READONLY)
raise ERROR_METRO_DATA, MESSAGE_READONLY
def get_header( self ):
"""
......@@ -312,6 +382,9 @@ class Metro_data:
return self.npMatrix.copy()
def is_multi_col( self, sCol_name ):
return len(self.index_of_matrix_col(sCol_name)) > 1
def get_matrix_col( self, sCol_name ):
"""
Name: get_matrix_col
......@@ -323,14 +396,26 @@ class Metro_data:
Descriptions: Get a copy of a matrix column identified by sCol_name.
"""
iCol = self.index_of_matrix_col(sCol_name)
# FFTODO get multi col
if self.is_multi_col(sCol_name):
begin = self.index_of_matrix_col(sCol_name)[0]
end = self.index_of_matrix_col(sCol_name)[-1]
returnList = []
for i in range(begin,end+1):
returnList.append(self.npMatrix[:,i].copy())
return returnList
else:
iCol = self.index_of_matrix_col(sCol_name)[0]
return self.npMatrix[:,iCol].copy()
return self.npMatrix[:,iCol].copy()
def index_of_matrix_col( self, sCol_name ):
"""Get index value of a matrix column identified by sCol_name."""
if sCol_name in self.lMatrix_col_name:
return self.lMatrix_col_name.index(sCol_name)
index = self.lMatrix_col_name.index(sCol_name)
return self.lMatrix_col_usage[index]
else:
sMatrix_col_list = metro_util.list2string(self.lMatrix_col_name)
sError = _("%s is not a valid column name. Valid column name ") \
......@@ -346,6 +431,13 @@ class Metro_data:
"""Get number of matrix column."""
return len(self.lMatrix_col_name)
def get_real_nb_matrix_col( self ):
"""Get real number of matrix column."""
if self.lMatrix_col_usage == []:
return 0
else:
return self.lMatrix_col_usage[-1][-1] + 1
def del_matrix_row(self, npIndiceToRemove):
"""
......
......@@ -67,7 +67,7 @@ class Metro_data_collection_output(Metro_data_collection):
self.subsampled_data = copy.deepcopy(data)
self.subsampled_data.init_matrix(0,
self.subsampled_data.\
get_nb_matrix_col())
get_real_nb_matrix_col())
def set_raw_data( self, data ):
......
......@@ -321,8 +321,11 @@ class Metro_model(Metro_module):
'XML_ROADCAST_PREDICTION_STANDARD_ITEMS')
lExtended_items = metro_config.get_value( \
'XML_ROADCAST_PREDICTION_EXTENDED_ITEMS')
lItems = lStandard_items + lExtended_items
lItems = lStandard_items # + lExtended_items
#FFTODO append all lExtended_items to metrodata
roadcast = metro_data.Metro_data(lItems)
# Extraction of forecast data used to create the roadcasts.
wf_data = forecast.get_interpolated_data()
......@@ -361,11 +364,18 @@ class Metro_model(Metro_module):
lBB = (macadam.get_bb())[:iNb_timesteps]
lFP = (macadam.get_fp())[:iNb_timesteps]
lSST = (macadam.get_sst())[:iNb_timesteps]
# Temperature of levels under the ground.
nNbrVerticalLevel = macadam.get_nbr_levels()
lDepth = (macadam.get_depth())[:nNbrVerticalLevel]
lLT = (macadam.get_lt())[:nNbrVerticalLevel*iNb_timesteps]
if metro_config.get_value('TL') == True:
# Temperature of levels under the ground.
nNbrVerticalLevel = macadam.get_nbr_levels()
lDepth = (macadam.get_depth())[:nNbrVerticalLevel]
lTmpTL = (macadam.get_lt())[:nNbrVerticalLevel*iNb_timesteps]
lTL = []
for i in range(0,iNb_timesteps):
begin = i * nNbrVerticalLevel
end = begin + nNbrVerticalLevel
lTL.append(lTmpTL[begin:end])
# Adding the informations to the header
roadcast.set_header_value('VERSION',sRoadcast_version)
roadcast.set_header_value('ROAD_STATION',sRoadcast_station)
......@@ -373,6 +383,9 @@ class Metro_model(Metro_module):
roadcast.set_header_value('LATITUDE', station.get_header()['COORDINATE'][0])
roadcast.set_header_value('LONGITUDE', station.get_header()['COORDINATE'][1])
roadcast.set_header_value('FILETYPE','roadcast')
if metro_config.get_value('TL') == True:
roadcast.set_header_value('VERTICAL_LEVELS',lDepth)
# TODO MT: Le +30 est la pour que l'output soit au bon moment.
......@@ -391,7 +404,7 @@ class Metro_model(Metro_module):
npCC = wf_data.get_matrix_col('CC')[:iNb_timesteps]
roadcast.init_matrix(iNb_timesteps, roadcast.get_nb_matrix_col())
roadcast.init_matrix(iNb_timesteps, roadcast.get_real_nb_matrix_col())
# Data added to the roadcast matrix
roadcast.set_matrix_col('RA', lRA)
......@@ -415,7 +428,11 @@ class Metro_model(Metro_module):
roadcast.set_matrix_col('FP', lFP)
roadcast.set_matrix_col('CC', npCC)
roadcast.set_matrix_col('SST', lSST)
if metro_config.get_value('TL') == True:
roadcast.append_matrix_multiCol('TL', lTL)
# Creation of the object Metro_data_collection for the roadcast
lStandard_attributes = metro_config.get_value( \
'DATA_ATTRIBUTE_ROADCAST_STANDARD')
......
......@@ -171,8 +171,8 @@ class Metro_postprocess_subsample_roadcast(Metro_postprocess):
fCurrentTime = dElement_Array['HH'][i]*3600
# Forecast at every 20 minutes, i.e. 1200 seconds
lRCvect = [0]*rc_subsampled.get_nb_matrix_col()
lMatrix_line = [None]*rc_subsampled.get_nb_matrix_col()
lRCvect = [0]*rc_subsampled.get_real_nb_matrix_col()
lMatrix_line = [None]*rc_subsampled.get_real_nb_matrix_col()
# if current time is a 20 minute interval
# and roadcast time is >= roadcast start date
......@@ -180,8 +180,22 @@ class Metro_postprocess_subsample_roadcast(Metro_postprocess):
dElement_Array['ROADCAST_TIME'][i] >= fStartDate :
for sElement in dElement_Array.keys():
lMatrix_line[rc_subsampled.index_of_matrix_col(sElement)] = \
dElement_Array[sElement][i]
lIndexList = rc_subsampled.index_of_matrix_col(sElement)
if not rc_subsampled.is_multi_col(sElement) :
# single col
lMatrix_line[rc_subsampled.index_of_matrix_col(sElement)[0]] = \
dElement_Array[sElement][i]
else:
# multicol
# FFTODO optimisation could probably be done here
iCol = 0
for j in lIndexList:
lMatrix_line[j] = \
dElement_Array[sElement][iCol][i]
iCol +=1
# Ugly stuff. Don't know. No clue about the 600.
for j in range(int(max(1,i-600/metro_constant.fTimeStep)),\
int(min(iNb_timesteps,i+600/\
......@@ -197,7 +211,7 @@ class Metro_postprocess_subsample_roadcast(Metro_postprocess):
nTop = max(lRCvect)
nRCcode = lRCvect.index(nTop)+1
lMatrix_line[rc_subsampled.index_of_matrix_col('RC')] = nRCcode
lMatrix_line[rc_subsampled.index_of_matrix_col('RC')[0]] = nRCcode
# Adding the new line in the matrix
rc_subsampled.append_matrix_row(lMatrix_line)
......
......@@ -397,14 +397,28 @@ def save_command_line_parameter( lArgv, sShort_opt, lLong_opt ):
if o == "--level":
dConfig['TL']['VALUE'] = True
dTLDict= {'NAME':"TL",
'XML_TAG':"tl",
'DATA_TYPE':"LIST_LEVEL_TEMP"}
dVlHeader = {'NAME':"VERTICAL_LEVELS",
'XML_TAG':"vertical-levels",
'DATA_TYPE':"VERTICAL_LEVELS"}
dConfig['XML_ROADCAST_HEADER_EXTENDED_ITEMS'][\
'VALUE'].append(dVlHeader)
dTL= {'NAME':"TL",
'XML_TAG':"tl",
'DATA_TYPE':"LIST_LEVEL_TEMP"}
dConfig['XML_ROADCAST_PREDICTION_EXTENDED_ITEMS'][\
'VALUE'].append(dTLDict)
'VALUE'].append(dTL)
# Selftest value
if o == "--selftest":
print str(opts)
opts.append(("--level",""))
dConf['INIT_ROADCAST_START_DATE'] = "2004-01-30T20:00Z"
dConf['FILE_FORECAST_IN_FILENAME'] = \
......@@ -589,9 +603,20 @@ def set_default_value( ):
'WRITE':"metro_metro2dom_handler.write_list",
'CHILD':[{'NAME':"LEV-TEMP",
'XML_TAG':"lev-temp",
'DATA_TYPE':'REAL'}
'DATA_TYPE':'REAL',
'PRECISION':2}
]},
'VERTICAL_LEVELS': \
{'READ' :"",
'WRITE':"metro_metro2dom_handler.write_list",
'CHILD':[{'NAME':"DEPTH",
'XML_TAG':"depth",
'DATA_TYPE':'REAL',
'PRECISION':2}
]},
'ROADLAYER_TYPE': \
{'READ' :"metro_dom2metro_handler.read_roadlayer_type",
'WRITE':""},
......@@ -917,7 +942,7 @@ def set_default_value( ):
{'NAME':"FIRST_ROADCAST",
'XML_TAG':"first-roadcast",
'DATA_TYPE':"STRING"},
],
'FROM' :CFG_INTERNAL,
......
......@@ -56,27 +56,15 @@ def write_date( domDoc, sXml_tag, fDate ):
return metro_xml.create_text_node(domDoc, sXml_tag, sDate)
def write_list( domDoc, sXml_list_tag, lChildList, lValues ):
lValues=[0.2,3.4]
listNode = metro_xml.create_node( domDoc, sXml_list_tag)
# print "domDoc=" + str(domDoc)
# print "xmltag=" + str(sXml_tag1)
# print "lChildList=" + str(lChildList)
# print "toto=" + str(lValues)
#
# Get handler
#
dDef = lChildList[0]
sWriteHandler = metro_xml.get_handler('WRITE', dDef)
sImportHandlerCode = metro_xml.get_handler_import_code(sWriteHandler)
exec sImportHandlerCode
sXml_tag = dDef['XML_TAG']
......@@ -84,6 +72,7 @@ def write_list( domDoc, sXml_list_tag, lChildList, lValues ):
#
# Add value to listNode
#
num=0
for val in lValues:
# Construction of instruction doing the function call that will
# create the node
......@@ -91,8 +80,10 @@ def write_list( domDoc, sXml_list_tag, lChildList, lValues ):
exec sCode
metro_xml.set_attribute(nodeData,"num",str(num))
metro_xml.append_child(listNode,nodeData)
num+=1
return listNode
......
......@@ -287,6 +287,9 @@ def create_text_node( domDoc, sNode_name, sNode_value ):
def append_child( nodeParent, nodeChild ):
metro_xml_lib.append_child(nodeParent, nodeChild)
def set_attribute( node, sAttributeName, sAttributeValue ):
metro_xml_lib.set_attribute(node, sAttributeName, sAttributeValue)
def write_to_file( domDoc, sFilename ):
metro_xml_lib.write_xml_file(domDoc, sFilename)
......@@ -359,7 +362,18 @@ def create_node_tree_from_matrix( domDoc, nodeParent, sPrediction_xpath,
exec sImportHandlerCode
# Extraction of the data from the matrix
val = npData[metro_data_object.index_of_matrix_col(sTag)]
lIndexList = metro_data_object.index_of_matrix_col(sTag)
if not metro_data_object.is_multi_col(sTag):
# single col
val = npData[lIndexList[0]]
else:
# multi col
# FFTODO good candidate for optimisation
val = []
for i in lIndexList:
val.append(npData[i])
if dData_type[sData_type_name].has_key('CHILD'):
# Construction of instruction doing the function call that will
......
......@@ -151,6 +151,9 @@ class Metro_xml_libxml2:
doc = ctxt.doc()
doc.freeDoc()
#------------------
# creation d'un DOM
#------------------
def create_dom( self, sDoc_name ):
"""
......@@ -175,6 +178,9 @@ class Metro_xml_libxml2:
def create_node( self, domDoc, sNode_name ):
return libxml2.newNode(sNode_name)
def set_attribute( self, node, sAttributeName, sAttributeValue ):
node.setProp(sAttributeName, sAttributeValue)
def append_child( self, nodeParent, nodeChild ):
nodeParent.addChild(nodeChild)
......
......@@ -145,6 +145,11 @@ class Metro_xml_pyxml:
def create_node( self, domDoc, sNode_name ):
return domDoc.createElement(sNode_name)
def set_attribute( self, node, sAttributeName, sAttributeValue ):
pass
# FFTODO code that operation for pyxml
#node.setProp(sAttributeName, sAttributeValue)
def append_child( self, nodeParent, nodeChild ):
nodeParent.appendChild(nodeChild)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment