From e1c1cd8a1cdc54551ab022ba16f49b55716e61c8 Mon Sep 17 00:00:00 2001 From: Scott Staniewicz Date: Thu, 13 Apr 2023 20:53:34 -0400 Subject: [PATCH 1/3] create unique text file for solid.for to write to, fix #50 fix fortran compile error Error: IMPLICIT statement at (1) cannot follow data declaration statement at (2) use the text file argument --- src/pysolid/grid.py | 9 ++++----- src/pysolid/point.py | 11 ++++++----- src/pysolid/solid.for | 13 ++++++++----- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/pysolid/grid.py b/src/pysolid/grid.py index 3920943..0aa54cc 100644 --- a/src/pysolid/grid.py +++ b/src/pysolid/grid.py @@ -11,8 +11,8 @@ # pysolid.calc_solid_earth_tides_grid() -import datetime as dt import os +import tempfile import numpy as np from skimage.transform import resize @@ -74,9 +74,8 @@ def calc_solid_earth_tides_grid(dt_obj, atr, step_size=1e3, display=False, verbo s=(length, width), la=lat_step, lo=lon_step)) ## calc solid Earth tides and write to text file - txt_file = os.path.abspath('solid.txt') - if os.path.isfile(txt_file): - os.remove(txt_file) + fp = tempfile.NamedTemporaryFile(prefix="pysolid_", suffix='.txt') + txt_file = fp.name vprint('SOLID : calculating / writing data to txt file: {}'.format(txt_file)) @@ -101,7 +100,7 @@ def calc_solid_earth_tides_grid(dt_obj, atr, step_size=1e3, display=False, verbo tide_u = fc[:, 2].reshape(length, width) # remove the temporary text file - os.remove(txt_file) + fp.close() # resample to the input size if num_step > 1: diff --git a/src/pysolid/point.py b/src/pysolid/point.py index 07d109a..9ba0a9e 100644 --- a/src/pysolid/point.py +++ b/src/pysolid/point.py @@ -14,6 +14,7 @@ import collections import datetime as dt import os +import tempfile import numpy as np from matplotlib import pyplot as plt, ticker, dates as mdates @@ -170,14 +171,14 @@ def calc_solid_earth_tides_point_per_day(lat, lon, date_str, step_sec=60): raise ImportError(msg) ## calc solid Earth tides and write to text file - txt_file = os.path.abspath('solid.txt') - if os.path.isfile(txt_file): - os.remove(txt_file) + # create a temporary text file so it doesn't get overwritten by competing processes + fp = tempfile.NamedTemporaryFile(prefix="pysolid_", mode='w') + txt_file = fp.name # Run twice to circumvent fortran bug which cuts off last file in loop - Simran, Jun 2020 t = dt.datetime.strptime(date_str, '%Y%m%d') for _ in range(2): - solid_point(lat, lon, t.year, t.month, t.day, step_sec) + solid_point(txt_file, lat, lon, t.year, t.month, t.day, step_sec) ## read data from text file num_row = int(24 * 60 * 60 / step_sec) @@ -196,7 +197,7 @@ def calc_solid_earth_tides_point_per_day(lat, lon, date_str, step_sec=60): dt_out = np.array(dt_out) # remove the temporary text file - os.remove(txt_file) + fp.close() return dt_out, tide_e, tide_n, tide_u diff --git a/src/pysolid/solid.for b/src/pysolid/solid.for index 4cf31bd..4279bde 100644 --- a/src/pysolid/solid.for +++ b/src/pysolid/solid.for @@ -9,7 +9,7 @@ *** wget -r -l1 --no-parent -R "index.html*" -nH --cut-dirs=3 https://iers-conventions.obspm.fr/content/chapter7/software/dehanttideinel *** Z. Yunjun and S. Sangha, Sep 2020: modify solid() to solid_point/grid() as subroutines. - subroutine solid_grid(iyr,imo,idy,ihh,imm,iss, + subroutine solid_grid(txt_file,iyr,imo,idy,ihh,imm,iss, * glad0,steplat,nlat, * glod0,steplon,nlon) @@ -20,6 +20,7 @@ *** Returns: latitude, longitude, SET_east, SET_north, SET_up implicit double precision(a-h,o-z) + character(len=*), intent(in) :: txt_file dimension rsun(3),rmoon(3),etide(3),xsta(3) integer iyr,imo,idy,ihh,imm,iss integer nlat,nlon @@ -33,7 +34,7 @@ *** open output file lout=1 - open(lout,file='solid.txt',form='formatted',status='unknown') + open(lout,file=txt_file,form='formatted',status='unknown') write(lout,'(a)') '# program solid -- UTC version -- 2018jun01' *** constants @@ -174,15 +175,17 @@ 99 end *----------------------------------------------------------------------- - subroutine solid_point(glad,glod,iyr,imo,idy,step_sec) + subroutine solid_point(txt_file,glad,glod,iyr,imo,idy,step_sec) *** calculate SET at given location for one day with step_sec seconds resolution -*** Arguments: glad/glod - float, latitude/longitude in deg +*** Arguments: txt_file - string, output file name +*** glad/glod - float, latitude/longitude in deg *** iyr/imo/idy - int, start date/time in UTC *** step_sec - int, time step in seconds *** Returns: seconds, SET_east, SET_north, SET_up implicit double precision(a-h,o-z) + character(len=*), intent(in) :: txt_file dimension rsun(3),rmoon(3),etide(3),xsta(3) double precision glad,glod integer iyr,imo,idy @@ -196,7 +199,7 @@ *** open output file lout=1 - open(lout,file='solid.txt',form='formatted',status='unknown') + open(lout,file=txt_file,form='formatted',status='unknown') write(lout,'(a)') '# program solid -- UTC version -- 2018jun01' *** constants From f7a7f85690457f9c0a148c2aafb59d6dba7195f6 Mon Sep 17 00:00:00 2001 From: Scott Staniewicz Date: Thu, 13 Apr 2023 21:18:24 -0400 Subject: [PATCH 2/3] pass txt_file to solid_grid to fix failing CI --- src/pysolid/grid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pysolid/grid.py b/src/pysolid/grid.py index 0aa54cc..abcc06d 100644 --- a/src/pysolid/grid.py +++ b/src/pysolid/grid.py @@ -81,7 +81,7 @@ def calc_solid_earth_tides_grid(dt_obj, atr, step_size=1e3, display=False, verbo # Run twice to circumvent fortran bug which cuts off last file in loop - Simran, Jun 2020 for _ in range(2): - solid_grid(dt_obj.year, dt_obj.month, dt_obj.day, + solid_grid(txt_file, dt_obj.year, dt_obj.month, dt_obj.day, dt_obj.hour, dt_obj.minute, dt_obj.second, lat0, lat_step, length-1, lon0, lon_step, width-1) From c4bf8b7f8011a46b606f6c538331dedfe2d3416a Mon Sep 17 00:00:00 2001 From: Scott Staniewicz Date: Sat, 15 Apr 2023 09:49:23 -0400 Subject: [PATCH 3/3] use `with` for tempfile and args --- src/pysolid/grid.py | 45 ++++++++++++++++++++----------------------- src/pysolid/point.py | 33 +++++++++++++++---------------- src/pysolid/solid.for | 3 ++- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/pysolid/grid.py b/src/pysolid/grid.py index abcc06d..21f03dd 100644 --- a/src/pysolid/grid.py +++ b/src/pysolid/grid.py @@ -74,34 +74,31 @@ def calc_solid_earth_tides_grid(dt_obj, atr, step_size=1e3, display=False, verbo s=(length, width), la=lat_step, lo=lon_step)) ## calc solid Earth tides and write to text file - fp = tempfile.NamedTemporaryFile(prefix="pysolid_", suffix='.txt') - txt_file = fp.name - - vprint('SOLID : calculating / writing data to txt file: {}'.format(txt_file)) - - # Run twice to circumvent fortran bug which cuts off last file in loop - Simran, Jun 2020 - for _ in range(2): - solid_grid(txt_file, dt_obj.year, dt_obj.month, dt_obj.day, - dt_obj.hour, dt_obj.minute, dt_obj.second, - lat0, lat_step, length-1, - lon0, lon_step, width-1) - - ## read data from text file - vprint('PYSOLID: read data from text file: {}'.format(txt_file)) - grid_size = int(length * width) - fc = np.loadtxt(txt_file, - dtype=float, - usecols=(2,3,4), - delimiter=',', - skiprows=0, - max_rows=grid_size+100)[:grid_size] + with tempfile.NamedTemporaryFile(prefix="pysolid_", suffix=".txt") as fp: + vprint('SOLID : calculating / writing data to txt file: {}'.format(fp.name)) + + # Run twice to circumvent fortran bug which cuts off last file in loop + # - Simran, Jun 2020 + for _ in range(2): + solid_grid(fp.name, dt_obj.year, dt_obj.month, dt_obj.day, + dt_obj.hour, dt_obj.minute, dt_obj.second, + lat0, lat_step, length - 1, + lon0, lon_step, width - 1) + + ## read data from text file + vprint('PYSOLID: read data from text file: {}'.format(fp.name)) + grid_size = int(length * width) + fc = np.loadtxt(fp.name, + dtype=float, + usecols=(2,3,4), + delimiter=',', + skiprows=0, + max_rows=grid_size+100)[:grid_size] + tide_e = fc[:, 0].reshape(length, width) tide_n = fc[:, 1].reshape(length, width) tide_u = fc[:, 2].reshape(length, width) - # remove the temporary text file - fp.close() - # resample to the input size if num_step > 1: out_shape = (int(atr['LENGTH']), int(atr['WIDTH'])) diff --git a/src/pysolid/point.py b/src/pysolid/point.py index 9ba0a9e..37e644b 100644 --- a/src/pysolid/point.py +++ b/src/pysolid/point.py @@ -171,22 +171,22 @@ def calc_solid_earth_tides_point_per_day(lat, lon, date_str, step_sec=60): raise ImportError(msg) ## calc solid Earth tides and write to text file + # create a temporary text file so it doesn't get overwritten by competing processes - fp = tempfile.NamedTemporaryFile(prefix="pysolid_", mode='w') - txt_file = fp.name - - # Run twice to circumvent fortran bug which cuts off last file in loop - Simran, Jun 2020 - t = dt.datetime.strptime(date_str, '%Y%m%d') - for _ in range(2): - solid_point(txt_file, lat, lon, t.year, t.month, t.day, step_sec) - - ## read data from text file - num_row = int(24 * 60 * 60 / step_sec) - fc = np.loadtxt(txt_file, - dtype=float, - delimiter=',', - skiprows=0, - max_rows=num_row) + with tempfile.NamedTemporaryFile(prefix="pysolid_", suffix=".txt") as fp: + # Run twice to circumvent fortran bug which cuts off last file in loop + # - Simran, Jun 2020 + t = dt.datetime.strptime(date_str, '%Y%m%d') + for _ in range(2): + solid_point(fp.name, lat, lon, t.year, t.month, t.day, step_sec) + + ## read data from text file + num_row = int(24 * 60 * 60 / step_sec) + fc = np.loadtxt(fp.name, + dtype=float, + delimiter=',', + skiprows=0, + max_rows=num_row) tide_e = fc[:, 1].flatten() tide_n = fc[:, 2].flatten() @@ -196,9 +196,6 @@ def calc_solid_earth_tides_point_per_day(lat, lon, date_str, step_sec=60): dt_out = [t + dt.timedelta(seconds=sec) for sec in secs] dt_out = np.array(dt_out) - # remove the temporary text file - fp.close() - return dt_out, tide_e, tide_n, tide_u diff --git a/src/pysolid/solid.for b/src/pysolid/solid.for index 4279bde..0d1d1db 100644 --- a/src/pysolid/solid.for +++ b/src/pysolid/solid.for @@ -14,7 +14,8 @@ * glod0,steplon,nlon) *** calculate solid earth tides (SET) for one spatial grid given the date/time -*** Arguments: iyr/imo/idy/ihh/imm/iss - int, date/time for YYYY/MM/DD/HH/MM/SS +*** Arguments: txt_file - string, output file name +*** iyr/imo/idy/ihh/imm/iss - int, date/time for YYYY/MM/DD/HH/MM/SS *** glad0/glad1/steplat - float, north(Y_FIRST)/south/step(negative) in deg *** glod0/glod1/steplon - float, west(X_FIRST) /east /step(positive) in deg *** Returns: latitude, longitude, SET_east, SET_north, SET_up