Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
f98f9d3
Cmake file to compile readgsa.F90 fortran routine
Mar 3, 2026
628ccf9
Fortran routine to read background variances
Mar 3, 2026
611804f
Add subdirectory src and compile readgsa.F90 routine
Mar 4, 2026
4232b78
Install tune_br.py script
Mar 4, 2026
c890c37
Add comments for the different steps
Mar 4, 2026
ed7daa0
Install tunebr_config.ini file
Mar 4, 2026
1c55ece
TuneBR pure python modules
Mar 4, 2026
9413dae
tuneBR main script
Mar 4, 2026
f12f042
tuneBR config.ini file
Mar 4, 2026
d04b5ae
Add __init__.py file and expose clases
Mar 4, 2026
f96cb0a
use import readcov rather than import readgsa
Mar 4, 2026
543f270
replace ''.join() by Path
Mar 4, 2026
2d13951
Fix the import statement for Odb.py and config_env.py
Mar 4, 2026
f28bfe9
Locate the main script tunebr.py set the import path
Mar 4, 2026
cc0f46c
Replace path and filename by variables
Mar 4, 2026
7661ce6
Expose all available classes. To be imported by tunebr main script
Mar 4, 2026
2d21197
Clean and replace .join() by Path
Mar 4, 2026
2bb2664
Cleaning and comment. Add install statement
Mar 4, 2026
b722eef
simple file rename
Mar 4, 2026
8f3564e
Copy the tuneBR config.ini file
Mar 4, 2026
1691e3f
Fix end of file bug. Use JPIM for integers
Mar 4, 2026
b06d0a0
Privide .ini file
Mar 11, 2026
121a878
Adapt to odb4py
Mar 15, 2026
76be2cc
Adapt to odb4py
Mar 15, 2026
6b3ddbf
Adapte to odb4py
Mar 15, 2026
6ad4416
Use argparse
Mar 15, 2026
e784469
Add comment for the DCA file
Mar 15, 2026
b8e0b89
Add comment for the DCA files
Mar 15, 2026
26a72a8
Add a check for getargs
Mar 15, 2026
0382762
Add tune_br test script
Mar 15, 2026
ba36c70
tune_br bash script test
Mar 15, 2026
066abe1
Move odb to read_odb
Mar 15, 2026
95c681c
rename odb.py to read_odb.py
Mar 15, 2026
f35e234
Add read_odb.py
Mar 15, 2026
61f5b34
replace import odb by import read_odb
Mar 15, 2026
6f26606
Clean module part
idirdehmous Mar 21, 2026
88399b4
Add header python env
idirdehmous Mar 21, 2026
512c6b8
Module to handle the obstool dataframes
idirdehmous Mar 21, 2026
296554e
Compute the Hollingwoorth-Lonneberh and Desroziers stats
idirdehmous Mar 21, 2026
499cdc1
Build the needed sql query for obstool
idirdehmous Mar 21, 2026
5ff7c4f
All needed info about the obstypes are defined here
idirdehmous Mar 21, 2026
f004834
Basic module for performing I/O
idirdehmous Mar 21, 2026
e7394f5
python modules __ini__ file
idirdehmous Mar 21, 2026
fbf3f26
Set the obslist , the period and other vars according to the obstool.…
idirdehmous Mar 21, 2026
a81b147
Contains the methods called by obstool.py
idirdehmous Mar 21, 2026
02975ab
Add installation of obstool modules
idirdehmous Mar 21, 2026
b762eda
Add the obstool.py script
idirdehmous Mar 21, 2026
5b2fc91
obstool bash test script
idirdehmous Mar 21, 2026
f66a060
Include obstool.py testing
idirdehmous Mar 21, 2026
198d450
Compile readgsa.F90
idirdehmous Mar 21, 2026
4016917
Fix the import directory
idirdehmous Mar 21, 2026
029a48f
Expose the python modules to the main callers
idirdehmous Mar 21, 2026
6534da4
Add readgsa.so modules
idirdehmous Mar 21, 2026
48b7cab
use the directory modules as a package path
idirdehmous Mar 21, 2026
1ff262d
Fix import handle_df to .handle_df
idirdehmous Mar 21, 2026
a6cc98f
Fix import readgsa to .readcov
idirdehmous Mar 21, 2026
f520dc0
Import .io_base
idirdehmous Mar 21, 2026
7657365
import obstype_info
idirdehmous Mar 21, 2026
61e88db
import sql_build
idirdehmous Mar 21, 2026
2abe5ca
Set modules as a path package and use .import
idirdehmous Mar 21, 2026
1153b5e
Set modules as a path package and use .import
idirdehmous Mar 21, 2026
7b6ffe6
Fix the short documentation
idirdehmous Mar 21, 2026
3432847
Rewrite the short class decription
idirdehmous Mar 21, 2026
7733093
Rewrite the short class decription
idirdehmous Mar 21, 2026
9405e9d
Rewrite the short class decription
idirdehmous Mar 21, 2026
6a654c4
Correct a typo
idirdehmous Mar 21, 2026
989985e
Fix build_sql when a level condition exists
idirdehmous Mar 21, 2026
df8c141
Add try , except when creating DCA
idirdehmous Mar 26, 2026
50ab091
Add --force_extract option : extract ODB rows even if they are archived
idirdehmous Mar 26, 2026
9194597
Get the --force_extract option
idirdehmous Mar 26, 2026
e07cd70
Fix the build query when obstype ==9 ascat
idirdehmous Mar 29, 2026
2359bbc
Fix verbosity level
idirdehmous Mar 29, 2026
a7231eb
Fix the progress bar and verbosity
idirdehmous Mar 29, 2026
b7fc989
Add message for virtual en creation
idirdehmous Mar 29, 2026
bdcbea7
Fix the issue : obstype in select statement
idirdehmous Mar 31, 2026
43ddedf
Ensure rounding to 10-6
idirdehmous Mar 31, 2026
38519ca
Ensure rounding to 10-6
idirdehmous Mar 31, 2026
c8ae204
Ensure rounding to 10-6 and distance to integer
idirdehmous Mar 31, 2026
af9fbac
Add verbosity option
idirdehmous Mar 31, 2026
7e240d7
Remove intermediate print query
idirdehmous Mar 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,21 @@ endif()
set(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} ${bounds}")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${dialect}")


#
# Compile.
# .Compile
#
# compilation of readgsa.F90 routine as a python extention
add_subdirectory(src)


add_executable(jbdiagnose.x src/jbdiagnose.F90)
add_executable(cv_header_list.x src/cv_header_list.F90)
add_executable(prepdiacov.x src/prepdiacov.F90)
add_executable(clddet_analyzer.x src/clddet_analyzer.F90)



# install executables and scripts
install (TARGETS jbdiagnose.x
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ
Expand All @@ -46,6 +52,8 @@ install (TARGETS clddet_analyzer.x
DESTINATION libexec)



add_subdirectory (scripts)
add_subdirectory (modules)
add_subdirectory (share)
add_subdirectory (tests)
30 changes: 30 additions & 0 deletions modules/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
function (install_modules )
foreach (file ${ARGV})
get_filename_component (name_without_extension ${file} NAME_WE)
install (FILES ${file}
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ
DESTINATION modules )
endforeach ()
endfunction()


# __init__ file
install_modules (__init__.py)
# Py modules For tuneBR
install_modules (readgsa.so
gsacov.py
read_odb.py
config_env.py
sigma_bo.py )

# Py modules for obstool
install_modules (build_sql.py
conv_stats.py
handle_df.py
io_base.py
setting.py
utils.py
obstype_info.py)



17 changes: 17 additions & 0 deletions modules/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#-*- cvoding: utf-8 -*-

# TuneBR modules
from . import gsacov
from . import config_env
from . import sigma_bo
from . import read_odb


# Obstool modules
from . import conv_stats
from . import build_sql
from . import obstype_info
from . import io_base
from . import setting
from . import utils

153 changes: 153 additions & 0 deletions modules/build_sql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# -*- coding:utf-8 -*-
import os ,sys
from odb4py.utils import SqlParser



class SqlHandler:
"""
Class : @ Parse the different observation dictionaries and build the
SQL query according to obstype, codetype, varno , sensor and level range
@ Checks the SQL statement before sending.
Returns : The sql statement according to variable and varno

Methods : BuildQuery
CheckQuery


"""
def __init__(self ):

# For the moment !
self.obstool_select=None

#self.derozier_select=None
#self.jarvinen_select=None
return None


def BuildQuery(self , **kwarg ):
self.cols =",".join(kwarg["columns" ])[1:]
self.tabs =",".join(kwarg["tables" ])
self.obs_ =kwarg["obs"]
self.varno =kwarg["obsvano"]
self.ctype =kwarg["codetype"]
self.obst =kwarg["obstype"]
self.levels =kwarg["lrange"]
self.vtype =kwarg["vertco_type"]
self.vert_coord=kwarg["vertco"]
self.sensor =kwarg["sensor" ]
self.other =kwarg["remaining_sql"]


# Obstool columns and tables
self.obstool_select="SELECT "+self.cols+" FROM " +self.tabs

# Check obstype
type_list=[]
if self.obst is not None:
if isinstance (self.obst, list ):
for tp in self.obst:
if tp is not None:
type_list.append (" obstype =="+str( tp ) )
elif isinstance (self.obst, int ):
type_list.append (" obstype =="+str( self.obst ) )
else:
print(self.obs_, " : obstype must be integer or a list" )
sys.exit()

# Check varno
varno_list=[]
if self.varno is not None:
if isinstance (self.varno , list ) :
for vr in self.varno:
if vr is not None:
varno_list.append (" varno =="+str( vr ) )
elif isinstance( self.varno , int ):
varno_list.insert(0, " varno =="+ str(self.varno) )

else:
print(self.obs_ , ": varno must be integer ot list" )
sys.exit()

# Check codetype
"""
Not needed for the moment !
ctype_list=[""]
if self.ctype is not None:
if isinstance( self.ctype, list ):
for ct in self.ctype:
if ct is not None:
ctype_list.append (" codetype =="+str( ct ) )
elif isinstance( self.ctype , int ):
ctype_list.append( " codetype =="+str(self.ctype ) )
else:
print(self.obs_, ": codetype must be integer or list " )
sys.exit()"""


# Check sensor
sensor_list =[]
if self.sensor != None:
if isinstance (self.sensor , list ):
for s in self.sensor:
if s is not None:
sensor_list.append( " sensor=="+str(s) )
elif isinstance (self.sensor , int ):
sensor_list.append( " sensor =="+str( self.sensor ) )
else:
print(self.obs_, ": sensor must be integer or list" )
sys.exit()


# Check level range
level_list=[]
if self.levels != None :
if len (self.levels) <2 or len( self.levels ) > 2:
print ( "Level range must have two limites [l1 , l2], but got argument:", self.levels )
sys.exit(0)
elif not isinstance (self.levels[0], int ) or not isinstance ( self.levels [1], int):
print( "One or the both level limites in the list is/are not intger(s)" )
sys.exit(0)
elif self.levels[1] < self.levels[0]:
print( "Bottom level limit can't be greater than top level limit" )
sys.exit(0)
else:
l1 =str(self.levels[0] )
l2 =str(self.levels[1] )
level_cond="vertco_reference_1 >="+l1+" AND vertco_reference_1 <= "+l2
level_list.append(level_cond)


where_cond_list=[]
for tp in type_list:
if len( type_list) !=0 :
where_cond_list.append( "".join( ( tp ) ) )
for vr in varno_list:
if len( varno_list) !=0:
where_cond_list.append( " AND ".join( (tp, vr )) )
if len(level_list) !=0:
for lv in level_list:
where_cond_list.append( " AND ".join( (tp, vr , lv )) )

query=" "
if self.other !=None and len(where_cond_list) == 0:
query= self.obstool_select +" WHERE "+self.other

elif self.other !=None and len(where_cond_list) > 0:
for condition in where_cond_list:
query=self.obstool_select +" WHERE " + condition + " AND "+self.other

elif self.other ==None and len(where_cond) > 0:
for condition in where_cond_list:
query= self.obstool_select +" WHERE " + condition

return query



def CheckQuery(self , query ):
p =SqlParser()
nfunc =p.get_nfunc ( query ) # N Columns=N pure columns - N functions in the query
sql =p.clean_string ( query ) # Remove any unprintable character ( \r\t ....etc)
return nfunc , sql
49 changes: 49 additions & 0 deletions modules/config_env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
import os
import configparser


class TuneEnv:
"""
Class: Parse the sections and get the items as a dict
"""
def __init__(self, config ):
self.BeginDate= config.get('DATES', 'DATESTART')
self.EndDate = config.get('DATES', 'DATEEND' )
#self.ntaks = config.get('DATES', 'NSLICE' , fallback=2)
self.outfile = config.get('OPTIONS', 'OUTFILE' , fallback = "sigmabo_ratios" )
self.dca_cpu = config.get('OPTIONS' ,'DCA_CPU', fallback= 4 )
self.llverb = config.getboolean('OPTIONS' ,'LLVERB' , fallback="false")
self.lwrite = config.getboolean('OPTIONS' ,'LWRITE' , fallback="false")
self.lplot = config.getboolean('OPTIONS' ,'LPLOT' , fallback="false")
self.prog_bar = config.getboolean('OPTIONS' ,'PROGBAR', fallback="false")




pp = config.items("PATHS")
self.path_opt = { str(opt[0]):str(opt[1]) for opt in pp }

self.basedir =self.path_opt["BASEDIR"]
self.stabal =self.path_opt["STATFILE"]
self.odbpath =self.path_opt["ODBPATH"]
self.odb_template=self.path_opt["ODB_TEMPLATE"]
self.rows_path=self.path_opt["ROWS_PATH"]
self.tmp_dir =self.path_opt["WORKDIR"]

mm = config.items("MODEL")
self.model_opt= { str(opt[0]):str(opt[1]) for opt in mm }

self.cycle_inc =self.model_opt["CYCLE_INC"]
self.deltax =self.model_opt["DELTAX"]
self.nsmax =self.model_opt["NSMAX"]
self.nflev =self.model_opt["NFLEV"]
self.rednmc =self.model_opt["REDNMC"]
return None

def __Dicts__(self ):
PathAttr = self.path_opt
ModelAttr= self.model_opt
return PathAttr ,ModelAttr


Loading