ladim 2.0.0__py3-none-any.whl → 2.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ladim/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
- __version__ = '2.0.0'
1
+ __version__ = '2.0.2'
2
2
 
3
3
  from .main import main, run
ladim/__main__.py ADDED
@@ -0,0 +1,2 @@
1
+ from . import run
2
+ run()
ladim/gridforce/ROMS.py CHANGED
@@ -15,10 +15,12 @@ import glob
15
15
  import logging
16
16
  import numpy as np
17
17
  from netCDF4 import Dataset, num2date
18
-
19
18
  from ladim.sample import sample2D, bilin_inv
20
19
 
21
20
 
21
+ logger = logging.getLogger(__name__)
22
+
23
+
22
24
  class Grid:
23
25
  """Simple ROMS grid object
24
26
 
@@ -34,7 +36,7 @@ class Grid:
34
36
 
35
37
  def __init__(self, config):
36
38
 
37
- logging.info("Initializing ROMS-type grid object")
39
+ logger.info("Initializing ROMS-type grid object")
38
40
 
39
41
  # Grid file
40
42
  if "grid_file" in config["gridforce"]:
@@ -44,14 +46,14 @@ class Grid:
44
46
  files.sort()
45
47
  grid_file = files[0]
46
48
  else:
47
- logging.error("No grid file specified")
49
+ logger.error("No grid file specified")
48
50
  raise SystemExit(1)
49
51
 
50
52
  try:
51
53
  ncid = Dataset(grid_file)
52
54
  ncid.set_auto_mask(False)
53
55
  except OSError:
54
- logging.error("Could not open grid file " + grid_file)
56
+ logger.error("Could not open grid file " + grid_file)
55
57
  raise SystemExit(1)
56
58
 
57
59
  # Subgrid, only considers internal grid cells
@@ -242,7 +244,7 @@ class Forcing:
242
244
 
243
245
  def __init__(self, config, grid):
244
246
 
245
- logging.info("Initiating forcing")
247
+ logger.info("Initiating forcing")
246
248
 
247
249
  self._grid = grid # Get the grid object, make private?
248
250
  # self.config = config["gridforce"]
@@ -255,9 +257,9 @@ class Forcing:
255
257
  files = self.find_files(config["gridforce"])
256
258
  numfiles = len(files)
257
259
  if numfiles == 0:
258
- logging.error("No input file: {}".format(config["gridforce"]["input_file"]))
260
+ logger.error("No input file: {}".format(config["gridforce"]["input_file"]))
259
261
  raise SystemExit(3)
260
- logging.info("Number of forcing files = {}".format(numfiles))
262
+ logger.info("Number of forcing files = {}".format(numfiles))
261
263
 
262
264
  # ---------------------------
263
265
  # Overview of all the files
@@ -357,6 +359,7 @@ class Forcing:
357
359
  all_frames = [] # All time frames
358
360
  num_frames = {} # Number of time frames in each file
359
361
  for fname in files:
362
+ logger.info(f'Open forcing file {fname}')
360
363
  with Dataset(fname) as nc:
361
364
  new_times = nc.variables["ocean_time"][:]
362
365
  num_frames[fname] = len(new_times)
@@ -370,11 +373,11 @@ class Forcing:
370
373
  if np.any(I):
371
374
  i = I.nonzero()[0][0] + 1 # Index of first out-of-order frame
372
375
  oooframe = str(all_frames[i]).split('.')[0] # Remove microseconds
373
- logging.info(f"Time frame {i} = {oooframe} out of order")
374
- logging.critical("Forcing time frames not strictly sorted")
376
+ logger.info(f"Time frame {i} = {oooframe} out of order")
377
+ logger.critical("Forcing time frames not strictly sorted")
375
378
  raise SystemExit(4)
376
379
 
377
- logging.info(f"Number of available forcing times = {len(all_frames)}")
380
+ logger.info(f"Number of available forcing times = {len(all_frames)}")
378
381
  return all_frames, num_frames
379
382
 
380
383
  @staticmethod
@@ -382,8 +385,8 @@ class Forcing:
382
385
 
383
386
  time0 = all_frames[0]
384
387
  time1 = all_frames[-1]
385
- logging.info(f"First forcing time = {time0}")
386
- logging.info(f"Last forcing time = {time1}")
388
+ logger.info(f"First forcing time = {time0}")
389
+ logger.info(f"Last forcing time = {time1}")
387
390
  start_time = np.datetime64(config["start_time"])
388
391
  dt = np.timedelta64(int(config["dt"]), "s")
389
392
 
@@ -391,10 +394,10 @@ class Forcing:
391
394
  # ------------------------------------------------------
392
395
 
393
396
  if time0 > start_time:
394
- logging.error("No forcing at start time")
397
+ logger.error("No forcing at start time")
395
398
  raise SystemExit(3)
396
399
  if time1 < config["stop_time"]:
397
- logging.error("No forcing at stop time")
400
+ logger.error("No forcing at stop time")
398
401
  raise SystemExit(3)
399
402
 
400
403
  # Make a list steps of the forcing time steps
@@ -427,7 +430,7 @@ class Forcing:
427
430
  interpolate_velocity_in_time = True
428
431
  interpolate_ibm_forcing_in_time = False
429
432
 
430
- logging.debug("Updating forcing, time step = {}".format(t))
433
+ logger.debug("Updating forcing, time step = {}".format(t))
431
434
  if t in self.steps: # No time interpolation
432
435
  self.U = self.Unew
433
436
  self.V = self.Vnew
@@ -486,7 +489,7 @@ class Forcing:
486
489
 
487
490
  # Handle file opening/closing
488
491
  # Always read velocity before other fields
489
- logging.info("Reading velocity for time step = {}".format(n))
492
+ logger.info("Reading velocity for time step = {}".format(n))
490
493
 
491
494
  # If finished a file or first read (self._nc == "")
492
495
  if not self._nc: # First read
ladim/gridforce/zROMS.py CHANGED
@@ -18,6 +18,9 @@ from netCDF4 import Dataset, num2date
18
18
  from ladim.sample import sample2D
19
19
 
20
20
 
21
+ logger = logging.getLogger(__name__)
22
+
23
+
21
24
  class Grid:
22
25
  """Simple ROMS grid object
23
26
 
@@ -33,11 +36,11 @@ class Grid:
33
36
 
34
37
  def __init__(self, config):
35
38
 
36
- logging.info("Initializing zROMS grid object")
39
+ logger.info("Initializing zROMS grid object")
37
40
  try:
38
41
  ncid = Dataset(config["gridforce"]["grid_file"])
39
42
  except OSError:
40
- logging.error(
43
+ logger.error(
41
44
  "Grid file {} not found".format(config["gridforce"]["grid_file"])
42
45
  )
43
46
  raise SystemExit(1)
@@ -188,7 +191,7 @@ class Forcing:
188
191
 
189
192
  def __init__(self, config, grid):
190
193
 
191
- logging.info("Initiating forcing")
194
+ logger.info("Initiating forcing")
192
195
 
193
196
  self._grid = grid # Get the grid object, make private?
194
197
 
@@ -199,9 +202,9 @@ class Forcing:
199
202
  files.sort()
200
203
  numfiles = len(files)
201
204
  if numfiles == 0:
202
- logging.error("No input file: {}".format(config["gridforce"]["input_file"]))
205
+ logger.error("No input file: {}".format(config["gridforce"]["input_file"]))
203
206
  raise SystemExit(3)
204
- logging.info("Number of forcing files = {}".format(numfiles))
207
+ logger.info("Number of forcing files = {}".format(numfiles))
205
208
 
206
209
  # ----------------------------------------
207
210
  # Open first file for some general info
@@ -250,14 +253,14 @@ class Forcing:
250
253
  new_times = nc.variables["time"][:]
251
254
  times.extend(new_times)
252
255
  num_frames.append(len(new_times))
253
- logging.info("Number of available forcing times = {:d}".format(len(times)))
256
+ logger.info("Number of available forcing times = {:d}".format(len(times)))
254
257
 
255
258
  # Find first/last forcing times
256
259
  # -----------------------------
257
260
  time0 = num2date(times[0], time_units)
258
261
  time1 = num2date(times[-1], time_units)
259
- logging.info("time0 = {}".format(str(time0)))
260
- logging.info("time1 = {}".format(str(time1)))
262
+ logger.info("time0 = {}".format(str(time0)))
263
+ logger.info("time1 = {}".format(str(time1)))
261
264
  # print(time0)
262
265
  # print(time1)
263
266
  start_time = np.datetime64(config["start_time"])
@@ -269,10 +272,10 @@ class Forcing:
269
272
  # Use logging module for this
270
273
 
271
274
  if time0 > start_time:
272
- logging.error("No forcing at start time")
275
+ logger.error("No forcing at start time")
273
276
  raise SystemExit(3)
274
277
  if time1 < config["stop_time"]:
275
- logging.error("No forcing at stop time")
278
+ logger.error("No forcing at stop time")
276
279
  raise SystemExit(3)
277
280
 
278
281
  # Make a list steps of the forcing time steps
@@ -362,7 +365,7 @@ class Forcing:
362
365
  interpolate_velocity_in_time = True
363
366
  interpolate_ibm_forcing_in_time = False
364
367
 
365
- logging.debug("Updating forcing, time step = {}".format(t))
368
+ logger.debug("Updating forcing, time step = {}".format(t))
366
369
  if t in self.steps: # No time interpolation
367
370
  self.U = self.Unew
368
371
  self.V = self.Vnew
@@ -399,7 +402,7 @@ class Forcing:
399
402
 
400
403
  # Handle file opening/closing
401
404
  # Always read velocity before other fields
402
- logging.debug("Reading velocity for time step = {}".format(n))
405
+ logger.debug("Reading velocity for time step = {}".format(n))
403
406
  first = True
404
407
  if first: # Open file initiallt
405
408
  self._nc = Dataset(self._files[self.file_idx[n]])
ladim/main.py CHANGED
@@ -12,13 +12,14 @@ Lagrangian Advection and Diffusion Model
12
12
  # ---------------------------------
13
13
 
14
14
  import logging
15
-
16
15
  import ladim
17
-
18
16
  from .config import configure
19
17
  from .model import Model
20
18
 
21
19
 
20
+ logger = logging.getLogger(__name__)
21
+
22
+
22
23
  def main(config_stream, loglevel=logging.INFO):
23
24
  """Main function for LADiM"""
24
25
 
@@ -67,23 +68,23 @@ def run():
67
68
 
68
69
  args = parser.parse_args()
69
70
 
70
- logging.info(" ================================================")
71
- logging.info(" === Lagrangian Advection and Diffusion Model ===")
72
- logging.info(" ================================================\n")
71
+ logger.info(" ================================================")
72
+ logger.info(" === Lagrangian Advection and Diffusion Model ===")
73
+ logger.info(" ================================================\n")
73
74
 
74
- logging.info(f"ladim path: {ladim.__file__.strip('__init.py__')}")
75
- logging.info(f"ladim version: {ladim.__version__}\n")
76
- logging.info(f"python version: {sys.version.split()[0]}\n")
75
+ logger.info(f"ladim path: {ladim.__file__.strip('__init.py__')}")
76
+ logger.info(f"ladim version: {ladim.__version__}\n")
77
+ logger.info(f"python version: {sys.version.split()[0]}\n")
77
78
 
78
- logging.info(f" Configuration file: {args.config_file}")
79
- logging.info(f" loglevel = {logging.getLevelName(args.loglevel)}")
79
+ logger.info(f" Configuration file: {args.config_file}")
80
+ logger.info(f" loglevel = {logging.getLevelName(args.loglevel)}")
80
81
 
81
82
  # =============
82
83
  # Sanity check
83
84
  # =============
84
85
 
85
86
  if not Path(args.config_file).exists():
86
- logging.critical(f'Configuration file {args.config_file} not found')
87
+ logger.critical(f'Configuration file {args.config_file} not found')
87
88
  raise SystemExit(1)
88
89
 
89
90
  # ===================
@@ -92,7 +93,7 @@ def run():
92
93
 
93
94
  # Start message
94
95
  now = datetime.datetime.now().replace(microsecond=0)
95
- logging.info(f'LADiM simulation starting, wall time={now}')
96
+ logger.info(f'LADiM simulation starting, wall time={now}')
96
97
 
97
98
  fp = open(args.config_file, encoding='utf8')
98
99
  ladim.main(config_stream=fp, loglevel=args.loglevel)
@@ -100,4 +101,4 @@ def run():
100
101
  # Reset logging and print final message
101
102
  logging.getLogger().setLevel(logging.INFO)
102
103
  now = datetime.datetime.now().replace(microsecond=0)
103
- logging.info(f'LADiM simulation finished, wall time={now}')
104
+ logger.info(f'LADiM simulation finished, wall time={now}')
ladim/release.py CHANGED
@@ -53,7 +53,7 @@ class TextFileReleaser(Releaser):
53
53
  self._dataframe = None
54
54
 
55
55
  # Continuous release variables
56
- self._frequency = read_timedelta(frequency)
56
+ self._frequency = read_timedelta(frequency) / np.timedelta64(1, 's')
57
57
  self._last_release_dataframe = pd.DataFrame()
58
58
  self._last_release_time = np.int64(-4611686018427387904)
59
59
 
@@ -80,6 +80,12 @@ class TextFileReleaser(Releaser):
80
80
  stop_time=self.model.solver.time + self.model.solver.step,
81
81
  ).copy(deep=True)
82
82
 
83
+ # If there are no new particles, but the state is empty, we should
84
+ # still initialize the state by adding the appropriate columns
85
+ if (len(df) == 0) and ('X' not in self.model.state):
86
+ self.model.state.append(df.to_dict(orient='list'))
87
+ self._last_release_dataframe = df
88
+
83
89
  # If there are no new particles and we don't use continuous release,
84
90
  # we are done.
85
91
  continuous_release = bool(self._frequency)
@@ -99,7 +105,7 @@ class TextFileReleaser(Releaser):
99
105
  return
100
106
 
101
107
  # If we have continuous release, but there are no new particles and
102
- # the last release is NOT recent, we should replace the empty
108
+ # the last release is NOT recent, we should replace empty
103
109
  # dataframe with the previously released dataframe
104
110
  if continuous_release:
105
111
  if (len(df) == 0) and not last_release_is_recent:
@@ -148,6 +154,7 @@ class TextFileReleaser(Releaser):
148
154
  self._dataframe = self._csv_fname
149
155
 
150
156
  else:
157
+ # noinspection PyArgumentList
151
158
  with open_or_relay(self._csv_fname, 'r', encoding='utf-8') as fp:
152
159
  self._dataframe = load_release_file(
153
160
  stream=fp,
ladim/state.py CHANGED
@@ -122,6 +122,14 @@ class DynamicState(State):
122
122
  raise AttributeError(f'Attribute not defined: {item}')
123
123
  return self[item]
124
124
 
125
+ def __setattr__(self, item, value):
126
+ if item in list(self.__dict__.keys()) + ['_data', '_model', '_num_released', '_varnames']:
127
+ super().__setattr__(item, value)
128
+ elif item in self._data:
129
+ self._data[item] = value
130
+ else:
131
+ raise AttributeError(f"Attribute not defined: '{item}'")
132
+
125
133
  def __contains__(self, item):
126
134
  return item in self._data
127
135
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ladim
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: Lagrangian Advection and Diffusion Model
5
5
  Home-page: https://github.com/pnsaevik/ladim
6
6
  Author: Bjørn Ådlandsvik
@@ -1,20 +1,21 @@
1
- ladim/__init__.py,sha256=Ns1alQ3-vgq1Hh0sgRGMsYsmH5LnEReoG-M-ajzLg04,51
1
+ ladim/__init__.py,sha256=0i7KXjW3S0HuMuJqk69XKrsqQE9QUVTrXRDo6jNiFEM,51
2
+ ladim/__main__.py,sha256=8f07EMfxQllDZSgpak5ECyYHnfQFy8LaHl2xdC-aO9c,23
2
3
  ladim/config.py,sha256=6b0ikBrBnq_sSElgO2YcVtJHjQU0nyZsVyPV3q9fy5I,4233
3
4
  ladim/forcing.py,sha256=f4PpSwyilSScXeNyorTWLMgVTiat9htSLkCwAkRlJVM,3048
4
5
  ladim/grid.py,sha256=m6bQrGJ3cux7rqC8pbRXD86cOI-VQKF-XjP9m1jCIcY,2221
5
- ladim/main.py,sha256=wO91-nLd1gvF3V20XK5qRvvOIV4xoTOKiWFcbwV2oag,2812
6
+ ladim/main.py,sha256=EwBkmWwQG7I0_i-xjthSTeGsoALHH-MdQ1Vvf64lv_A,2838
6
7
  ladim/model.py,sha256=jpjq_ZSh7ULpwi3_RqDb-p5SG8WcdgCPaBkSpnNWblU,3137
7
8
  ladim/output.py,sha256=Rz7iujvS7Z3LoABiJduQqyb3zPswNqhhFsywr3MLsBY,8373
8
- ladim/release.py,sha256=5QD0hxQNmkxGmtrQX72T5QumHeWLQMFHysJD6Sc0BUE,8067
9
+ ladim/release.py,sha256=1j__9Gj0BD0CqVCM2KLZhio1Ia-hz1gbUIhTsa0J3Rg,8451
9
10
  ladim/sample.py,sha256=n8wRGd_VsW_qyQe1ZoTpmfZcdcwB929vsM8PoKG6JTs,8292
10
11
  ladim/solver.py,sha256=sZvYgOxzJ-EItI-IB2y8_z8Tf-SJAQSrmydlhDRa7ZQ,755
11
- ladim/state.py,sha256=5ICIiujsV3KOAUYagGLK7YdmhcItgJmtntZeR11nIpw,3781
12
+ ladim/state.py,sha256=4XNIIx5sGjlqkZ6bg-dGbqzp8ujFNkHHFL2D9qCQA2w,4119
12
13
  ladim/tracker.py,sha256=VVX6T5CqiU6nGSCgLlSCC8w0UYhW273OGFE7ApPjdyI,5091
13
14
  ladim/utilities.py,sha256=r7-zShqJhh0cBctDUmtfw-GBOk1eTTYR4S72b0ouiSQ,994
14
- ladim/gridforce/ROMS.py,sha256=yrMr1GiDgr7VG9V630nHFdeajPY4WHLu653ZRwAk1aw,26888
15
+ ladim/gridforce/ROMS.py,sha256=6y8ZIkAQgVPgK-zG53SKxFms4lJdkTCaP1doz7zuSyo,26965
15
16
  ladim/gridforce/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
17
  ladim/gridforce/analytical.py,sha256=qI-1LJdjmnwwanzOdrsDZqwGgo73bT75CB7pMaxbHKM,1094
17
- ladim/gridforce/zROMS.py,sha256=MVA6PQuY1ukvs2E20sWY4kr5-QieeQHTrA5ruxCqbUM,22826
18
+ ladim/gridforce/zROMS.py,sha256=t88mow91orUP-kMQiqmQ0_SnJKKG9xfycM5MMmdVljI,22853
18
19
  ladim/ibms/__init__.py,sha256=GOG75jZDmNEiLr8brxrKqIlqVj-pNR7pnPP8FUKE6hU,565
19
20
  ladim/ibms/light.py,sha256=POltHmKkX8-q3t9wXyfcseCKEq9Bq-kX1WEJYsr1lNQ,2737
20
21
  ladim/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -23,9 +24,9 @@ postladim/cellcount.py,sha256=nCFu9iJmprubn4YmPB4W0VO02GfEb90Iif7D49w1Kss,2054
23
24
  postladim/kde_plot.py,sha256=GvMWzT6VxIeXKh1cnqaGzR-4jGG_WIHGMLPpRMXIpo4,1628
24
25
  postladim/particlefile.py,sha256=0aif9wYUJ-VrpQKeCef8wB5VCiBB-gWY6sxNCUYviTA,4889
25
26
  postladim/variable.py,sha256=-2aihoppYMMmpSpCqaF31XvpinTMaH3Y01-USDIkbBc,6587
26
- ladim-2.0.0.dist-info/LICENSE,sha256=BgtXyjNr6Ly9nQ7ZLXKpV3r5kWRLnh5MiN0dxp0Bvfc,1085
27
- ladim-2.0.0.dist-info/METADATA,sha256=ap0yaeqHIhnmQiMwuH8gaCT__YNxESVoudzgFuko9Zs,1841
28
- ladim-2.0.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
29
- ladim-2.0.0.dist-info/entry_points.txt,sha256=JDlNJo87GJaOkH0-BpAzTPLCrZcuPSdSlHNQ4XmnoRg,41
30
- ladim-2.0.0.dist-info/top_level.txt,sha256=TK8Gl7d6MsrAQvqKG4b6YJCbB4UL46Se3SzsI-sJAuc,16
31
- ladim-2.0.0.dist-info/RECORD,,
27
+ ladim-2.0.2.dist-info/LICENSE,sha256=BgtXyjNr6Ly9nQ7ZLXKpV3r5kWRLnh5MiN0dxp0Bvfc,1085
28
+ ladim-2.0.2.dist-info/METADATA,sha256=sjw274vLpD7oaf1g96Ik4VEI0c2grbLVml7nVXTVfoU,1841
29
+ ladim-2.0.2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
30
+ ladim-2.0.2.dist-info/entry_points.txt,sha256=JDlNJo87GJaOkH0-BpAzTPLCrZcuPSdSlHNQ4XmnoRg,41
31
+ ladim-2.0.2.dist-info/top_level.txt,sha256=TK8Gl7d6MsrAQvqKG4b6YJCbB4UL46Se3SzsI-sJAuc,16
32
+ ladim-2.0.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes