Skip to content
Open
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
666a675
Apply safe ruff autofixes in remap_restart
mathomp4 Oct 15, 2026
c886220
Ignore __pycache__ directories at any depth
mathomp4 Oct 15, 2026
0509251
Remove unused variables and imports flagged by ruff
mathomp4 Oct 15, 2026
f556609
Use sys.exit() instead of the site-provided exit()
mathomp4 Oct 15, 2026
524f7b6
Use context managers for file handling
mathomp4 Oct 15, 2026
9ef00c2
Apply remaining ruff style cleanups
mathomp4 Oct 15, 2026
f27a3e0
Replace star imports with explicit imports
mathomp4 Oct 15, 2026
954bb30
Fail loudly on subprocess errors (check=True, drop os.system)
mathomp4 Oct 15, 2026
d050737
Fix shutil.remove -> os.remove; default bc_version to empty string
mathomp4 Oct 15, 2026
5f98d9f
Add ruff configuration for remap_restart
mathomp4 Oct 15, 2026
4a5880f
Use ruff.toml instead of pyproject.toml
mathomp4 Oct 15, 2026
6e159e2
Remove scratch directories after successful remaps
mathomp4 Oct 15, 2026
11c5ed7
Restore catch_model() definition deleted by accident; drop noqa
mathomp4 Oct 15, 2026
8845db6
Move Python ignores to the repo root and add ruff/pytest/venv
mathomp4 Oct 15, 2026
f1245ae
Make v14 the default BCs version in the remap questions
mathomp4 Oct 15, 2026
6715a12
Keep v12 in the main BCs menu; drop v12/v14 from Other
mathomp4 Oct 15, 2026
a8b68b0
NL3 GCM tag range now ends at 11.9
mathomp4 Oct 15, 2026
7b9ab9f
Write remap_params.yaml without line wrapping (fixes trailing space a…
mathomp4 Oct 15, 2026
d08eda0
Update CHANGELOG for remap_restart changes
mathomp4 Oct 15, 2026
6972ded
Add GitHub Action for ruff and ty checks on remap_restart
mathomp4 Oct 15, 2026
7ec0844
get_resolutions: error clearly on missing agrid/ogrid; make ty blocki…
mathomp4 Oct 15, 2026
f173ac9
Update astral actions to Node 24 versions; disable uv cache
mathomp4 Oct 15, 2026
0ed48ef
Pin astral actions to full release tags
mathomp4 Oct 15, 2026
545a47b
Move v12 BCs from ops to other list; add GCM tags to other table
mathomp4 Oct 15, 2026
9ec01c6
Order other BCs choices by version
mathomp4 Oct 15, 2026
908519e
Restore v12 BCs description from history
mathomp4 Oct 15, 2026
92db16b
added info about v14 bcs in remap_utils.py
gmao-rreichle Oct 15, 2026
dec2758
Reordered choices_bc_other list, expanded m in remap_utils.py
gmao-rreichle Oct 16, 2026
8cd5020
revised bc choices and messages for drawdown menus
gmao-rreichle Oct 16, 2026
a9f800e
renamed 2nd list of choices in drawdown menu from from "other" to "al…
gmao-rreichle Oct 16, 2026
95ad41f
Ignore sorting on some import lists
mathomp4 Oct 16, 2026
a13d85a
Remove v15_BETA from BC selection options
biljanaorescanin Oct 19, 2026
a592802
Fix BC string after removing v15_BETA
biljanaorescanin Oct 19, 2026
e541a02
Fix All BC menu conditions and simplify output selection
biljanaorescanin Oct 19, 2026
e575a44
Merge branch 'main' into feature/ruff-fix-remap
biljanaorescanin Nov 2, 2026
0d5d0e8
Merge branch 'main' into feature/ruff-fix-remap
sdrabenh Nov 6, 2026
4a72de4
Merge branch 'main' into feature/ruff-fix-remap
sdrabenh Nov 6, 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
32 changes: 32 additions & 0 deletions .github/workflows/python-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Python Lint

on:
pull_request:
paths:
- 'pre/remap_restart/**'
- '.github/workflows/python-lint.yml'

jobs:
ruff:
name: ruff
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/ruff-action@v4.1.0
with:
src: pre/remap_restart

ty:
name: ty
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: astral-sh/setup-uv@v10.3.0
with:
enable-cache: false
- name: Run ty
working-directory: pre/remap_restart
run: |
uv venv
uv pip install ty numpy netCDF4 scipy pyyaml ruamel.yaml questionary
uv run ty check --python .venv .
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@
*#
.#*
**/CVS/

# Python
__pycache__/
*.py[cod]
.ruff_cache/
.pytest_cache/
.venv/
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added plots for EDMF
- Added new column and cloud variables and fixed bugs.

- Added `ruff.toml` for `pre/remap_restart`
- Added a GitHub Action (`python-lint.yml`) that runs `ruff` and `ty` on `pre/remap_restart`
- Added Python ignores (`__pycache__/`, `.ruff_cache/`, `.pytest_cache/`, `.venv/`) to the root `.gitignore`

### Changed
- Updated plot seasons in plot.rc
- Cleaned up `pre/remap_restart` Python code per ruff: explicit imports in place of star imports, context managers for file handling, `sys.exit()` in place of `exit()`, and other style fixes
- `remap_restarts` now makes v14 the default BCs version in the interactive questions; v12 remains in the main menu, and v11, v13 and v15_BETA remain under "Other"
- `remap_restarts` now removes its scratch directories (`InData/`, `OutData/`, `upper_data/`, `ana_data/`) after a successful remap
- Subprocess failures in `remap_restarts` now raise an error instead of being ignored
- `remap_params.yaml` is now written without line wrapping

### Fixed

- Fixed `shutil.remove` calls (now `os.remove`) in `remap_other_restarts.py`
- Fixed a `TypeError` in `remap_utils.py` when `bc_version` is missing
- Fixed a trailing space after `bc_base:` in the generated `remap_params.yaml`
- `get_resolutions` in `remap_utils.py` now raises a clear error if `agrid` or `ogrid` is missing

### Removed

### Deprecated
Expand Down
1 change: 0 additions & 1 deletion pre/remap_restart/.gitignore

This file was deleted.

45 changes: 20 additions & 25 deletions pre/remap_restart/remap_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
# source g5_modules.sh [bash]
# source g5_modules [csh]
#
import fnmatch
import glob
import os
from datetime import datetime, timedelta
import subprocess
import shlex
import shutil
import glob
import fileinput
import ruamel.yaml
import subprocess
from datetime import datetime, timedelta

from remap_base import remap_base
from remap_utils import get_label, MERRA2_RST_BASE
import fnmatch
from remap_utils import MERRA2_RST_BASE, get_label


class analysis(remap_base):
def __init__(self, **configs):
Expand Down Expand Up @@ -56,11 +56,7 @@ def remap(self):
os.chdir(tmpdir)

yyyymmddhh_ = str(config['input']['shared']['yyyymmddhh'])
yyyy_ = yyyymmddhh_[0:4]
mm_ = yyyymmddhh_[4:6]
dd_ = yyyymmddhh_[6:8]
hh_ = yyyymmddhh_[8:10]
rst_time = datetime(year=int(yyyy_), month=int(mm_), day=int(dd_), hour = int(hh_))
expid_in = config['input']['shared']['expid']
expid_out = config['output']['shared']['expid']
if (expid_out) :
Expand All @@ -83,13 +79,10 @@ def remap(self):
f_tmp = tmpdir+'/'+out_name
local_fs.append(f_tmp)
shutil.copy(f,f_tmp)
if out_name.find('satbias') != -1 :
if (aqua):
f_ = open(f_tmp, 'w')
for line in fileinput.input(f):
if out_name.find('satbias') != -1 and aqua:
with open(f) as f_in, open(f_tmp, 'w') as f_:
# This is unlikely to be the case with new files
f_.write(line.replace('airs281SUBSET_aqua', 'airs281_aqua '))
f_.close()
f_.writelines(line.replace('airs281SUBSET_aqua', 'airs281_aqua ') for line in f_in)

nlevel = config['output']['air']['nlevel']
agrid_out = config['output']['shared']['agrid']
Expand All @@ -102,7 +95,7 @@ def remap(self):
shutil.move(f,f_orig)
cmd = bindir + '/dyn2dyn.x ' + flags + ' -o ' + f + ' ' + f_orig
print(cmd)
subprocess.call(shlex.split(cmd))
subprocess.run(shlex.split(cmd), check=True)

for f in local_fs:
fname = os.path.basename(f)
Expand All @@ -124,9 +117,11 @@ def remap(self):
rstlcvOut = out_dir+'/'+expid_out+'rst.lcv.'+ymd_+'_'+hh_+'z.bin' + label
cmd = bindir+'/mkdrstdate.x ' + ymd_ + ' ' + hms_ +' ' + rstlcvOut
print(cmd)
subprocess.call(shlex.split(cmd))
subprocess.run(shlex.split(cmd), check=True)
print( "cd " + cwdir)
os.chdir(cwdir)
print("remove " + tmpdir)
shutil.rmtree(tmpdir)

if self.config['input']['shared']['MERRA-2']:
self.remove_merra2()
Expand Down Expand Up @@ -187,10 +182,10 @@ def copy_merra2(self):
delt = timedelta(hours = h-3)
new_time = rst_time + delt
yyyy = "Y"+str(new_time.year)
mm = 'M%02d'%new_time.month
ymd = '%04d%02d%02d'%(new_time.year,new_time.month, new_time.day)
hh = '%02d'%h
newhh= '%02d'%new_time.hour
mm = f'M{new_time.month:02d}'
ymd = f'{new_time.year:04d}{new_time.month:02d}{new_time.day:02d}'
hh = f'{h:02d}'
newhh= f'{new_time.hour:02d}'
m2_rst_dir = merra_2_rst_dir.replace('Y'+yyyy_,yyyy).replace('M'+mm_,mm)
# bkg files
for ftype in ['sfc', 'eta']:
Expand Down Expand Up @@ -231,8 +226,8 @@ def copy_merra2(self):
delt = timedelta(hours = 3)
new_time = rst_time - delt
yyyy = "Y"+str(new_time.year)
mm = 'M%02d'%new_time.month
ymdh = '%04d%02d%02d%02d'%(new_time.year, new_time.month, new_time.day, new_time.hour)
mm = f'M{new_time.month:02d}'
ymdh = f'{new_time.year:04d}{new_time.month:02d}{new_time.day:02d}{new_time.hour:02d}'
m2_rst_dir = merra_2_rst_dir.replace('Y'+yyyy_,yyyy).replace('M'+mm_,mm)
fname = expid+'.trak.GDA.rst.'+ymdh+'z.txt'
f = m2_rst_dir+'/'+fname
Expand Down
15 changes: 9 additions & 6 deletions pre/remap_restart/remap_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
# remap_base.py does [???]
#
import os
import ruamel.yaml
import shlex
import shutil
import subprocess
from remap_utils import *

class remap_base(object):
import netCDF4 as nc

from remap_utils import GEOSIT_RST_BASE, get_config_from_file


class remap_base:
def __init__(self, **configs):
for key, value in configs.items():
if (key == 'params_file'):
Expand Down Expand Up @@ -73,8 +77,7 @@ def copy_without_remap(self, restarts_in, compared_file_in, compared_file_out, s
if diff != 0: return False

# for catchment, even tile files are the same, if bc is different, it still need remap
if (catch) :
if in_bc_version != out_bc_version : return False
if catch and in_bc_version != out_bc_version : return False

expid = config['output']['shared']['expid']
if (expid) :
Expand All @@ -88,7 +91,7 @@ def copy_without_remap(self, restarts_in, compared_file_in, compared_file_out, s
f = expid + os.path.basename(rst).split('_rst')[0].split('.')[-1]+'_rst.'+suffix
cmd = '/bin/cp ' + rst + ' ' + out_dir+'/'+f
print('\n'+cmd)
subprocess.call(shlex.split(cmd))
subprocess.run(shlex.split(cmd), check=True)

return True

Expand Down
50 changes: 25 additions & 25 deletions pre/remap_restart/remap_bin2nc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
# remapped. The set of yaml config files "bin2nc_merra2_*.yaml" include hard-wired
# variables names, long names, and tile/grid dimensions specific to MERRA-2 restarts.

from yaml import safe_load, load, dump
from netCDF4 import Dataset
import numpy as np
from netCDF4 import Dataset
from scipy.io import FortranFile
from yaml import dump, safe_load


def writeCVars(coordVars,dimensions):

Expand Down Expand Up @@ -73,36 +74,36 @@ def defineDimVars(fid,dims):
for d in dims:
if d=="lon":
newVar=fid.createVariable(d,'f8',d)
setattr(newVar,'units','degrees_east')
setattr(newVar,'long_name','Longitude')
newVar.units = 'degrees_east'
newVar.long_name = 'Longitude'
coordVars.update([(d,newVar)])
if d=="lat":
newVar=fid.createVariable(d,'f8',d)
setattr(newVar,'units','degrees_north')
setattr(newVar,'long_name','Latitude')
newVar.units = 'degrees_north'
newVar.long_name = 'Latitude'
coordVars.update([(d,newVar)])
if d=="lev":
newVar=fid.createVariable(d,'f8',d)
setattr(newVar,'units','layer')
setattr(newVar,'long_name','sigma_at_layer_midpoints')
setattr(newVar,'standard_name','atmosphere_hybrid_sigma_pressure_coordinate')
setattr(newVar,'coordinate','eta')
setattr(newVar,'positive','down')
setattr(newVar,'formulaTerms','ap: ak b: bk ps: ps p0: p00')
newVar.units = 'layer'
newVar.long_name = 'sigma_at_layer_midpoints'
newVar.standard_name = 'atmosphere_hybrid_sigma_pressure_coordinate'
newVar.coordinate = 'eta'
newVar.positive = 'down'
newVar.formulaTerms = 'ap: ak b: bk ps: ps p0: p00'
coordVars.update([(d,newVar)])
if d=="edge":
newVar=fid.createVariable(d,'f8',d)
setattr(newVar,'units','level')
setattr(newVar,'long_name','sigma_at_layer edge')
setattr(newVar,'standard_name','atmosphere_hybrid_sigma_pressure_coordinate')
setattr(newVar,'coordinate','eta')
setattr(newVar,'positive','down')
setattr(newVar,'formulaTerms','ap: ak b: bk ps: ps p0: p00')
newVar.units = 'level'
newVar.long_name = 'sigma_at_layer edge'
newVar.standard_name = 'atmosphere_hybrid_sigma_pressure_coordinate'
newVar.coordinate = 'eta'
newVar.positive = 'down'
newVar.formulaTerms = 'ap: ak b: bk ps: ps p0: p00'
coordVars.update([(d,newVar)])
if d=="time":
newVar=fid.createVariable(d,'f8',d)
setattr(newVar,'units','minutes since ')
setattr(newVar,'long_name','time')
newVar.units = 'minutes since '
newVar.long_name = 'time'
coordVars.update([(d,newVar)])

return coordVars
Expand All @@ -114,9 +115,8 @@ def bin2nc(binfile, ncfile, yamlfile, isDouble=False, hasHeader=False, debug=Fal
bintype=np.float64


f=open(yamlfile,'r')

data=safe_load(f)
with open(yamlfile,'r') as f:
data=safe_load(f)

dimensions = data["dimensions"]
variables = data["variables"]
Expand All @@ -142,8 +142,8 @@ def bin2nc(binfile, ncfile, yamlfile, isDouble=False, hasHeader=False, debug=Fal
units = v['units']
dims = v['dimension']
newVar = ncfid.createVariable(sname,'f4',dims)
setattr(newVar,'long_name',lname)
setattr(newVar,'units',units)
newVar.long_name = lname
newVar.units = units
vars.update([(sname,newVar)])

writeCVars(cVars,dimensions)
Expand Down
Loading
Loading