PyMVP 0.2.4__tar.gz → 0.2.5__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyMVP
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: Python package for Moving Vessel Profiler correction and analysis
5
5
  Author: MaximilienWemaere
6
6
  Requires-Python: >=3.10
@@ -1333,7 +1333,6 @@ class Analyzer:
1333
1333
  for id_mvp in range(0,self.PRES_mvp.shape[0]):
1334
1334
 
1335
1335
  id_nearest_ctd = mvp.find_nearest_profile(self.TIME_mvp_corr_interp[id_mvp],self.Lat_mvp_corr_interp[id_mvp], self.Lon_mvp_corr_interp[id_mvp],self.TIME_ctd ,self.LAT_ctd, self.LON_ctd,mode)[0]
1336
- print(id_mvp,id_nearest_ctd)
1337
1336
  self.correct_oxygen(id_mvp=id_mvp, id_ctd=id_nearest_ctd, plotting=False)
1338
1337
 
1339
1338
  print("Oxygen correction applied to all MVP profiles using nearest CTD profiles.")
@@ -1503,7 +1502,6 @@ class Analyzer:
1503
1502
  print("Mean conductivity difference between MVP and CTD profiles:", np.mean(mean_cond_diff))
1504
1503
 
1505
1504
 
1506
-
1507
1505
  def corrige_MVP_offset_on_ctd_simple(self,id_mvp,id_ctd,min_depth):
1508
1506
  """
1509
1507
  This function corrects the offset between the MVP and CTD profiles by aligning the temperature, conductivity profiles. It calculates the mean difference in temperature between the two profiles and applies this correction to the CTD temperature data.
@@ -1553,235 +1551,241 @@ class Analyzer:
1553
1551
  print("Mean conductivity difference between MVP and CTD profiles:", np.mean(mean_cond_diff))
1554
1552
 
1555
1553
 
1554
+ def corrige_MVP_offset_on_ctd_all(self,min_depth,mode):
1556
1555
 
1556
+ for id_mvp in range(self.PRES_mvp.shape[0]):
1557
+ id_nearest_ctd = mvp.find_nearest_profile(self.TIME_mvp_corr_interp[id_mvp],self.Lat_mvp_corr_interp[id_mvp], self.Lon_mvp_corr_interp[id_mvp],self.TIME_ctd ,self.LAT_ctd, self.LON_ctd,mode)[0]
1558
+ self.corrige_MVP_offset_on_ctd_simple(id_mvp=id_mvp, id_ctd=id_nearest_ctd, min_depth=min_depth)
1557
1559
 
1558
- def to_netcdf(self, filepath, corrected=False, compression=True, engine=None, per_profile_files=False):
1559
- """
1560
- Export MVP data to a NetCDF file using xarray.
1560
+ print("MVP profiles corrected for offset against CTD profiles using nearest CTD profiles.")
1561
1561
 
1562
- Args:
1563
- filepath (str): Output NetCDF file path.
1564
- corrected (bool): Also write corrected arrays if present (*_mvp_corr). Default False.
1565
- compression (bool): Enable compression (engine dependent). Default True.
1566
- engine (str|None): One of 'netcdf4', 'h5netcdf', 'scipy'. If None, choose netcdf4.
1567
- per_profile_files (bool): If True, write one .nc per MVP cycle (two rows: down and up).
1568
- """
1569
- if not getattr(self, 'mvp', False):
1570
- raise RuntimeError("No MVP data loaded. Call load_mvp_data() first.")
1562
+ def to_netcdf(self, filepath, corrected=False, compression=True, engine=None, per_profile_files=False):
1563
+ """
1564
+ Export MVP data to a NetCDF file using xarray.
1565
+
1566
+ Args:
1567
+ filepath (str): Output NetCDF file path.
1568
+ corrected (bool): Also write corrected arrays if present (*_mvp_corr). Default False.
1569
+ compression (bool): Enable compression (engine dependent). Default True.
1570
+ engine (str|None): One of 'netcdf4', 'h5netcdf', 'scipy'. If None, choose netcdf4.
1571
+ per_profile_files (bool): If True, write one .nc per MVP cycle (two rows: down and up).
1572
+ """
1573
+ if not getattr(self, 'mvp', False):
1574
+ raise RuntimeError("No MVP data loaded. Call load_mvp_data() first.")
1571
1575
 
1572
- engine = 'netcdf4' if engine is None else engine
1573
- if engine == 'scipy' and compression:
1574
- print('Warning: scipy backend does not support compression; writing without compression.')
1575
- compression = False
1576
+ engine = 'netcdf4' if engine is None else engine
1577
+ if engine == 'scipy' and compression:
1578
+ print('Warning: scipy backend does not support compression; writing without compression.')
1579
+ compression = False
1576
1580
 
1577
- # Dimensions
1578
- n_prof, n_samp = self.PRES_mvp.shape
1581
+ # Dimensions
1582
+ n_prof, n_samp = self.PRES_mvp.shape
1579
1583
 
1580
- # Coordinates
1581
- profile_idx = np.arange(n_prof, dtype=np.int32)
1582
- sample_idx = np.arange(n_samp, dtype=np.int32)
1584
+ # Coordinates
1585
+ profile_idx = np.arange(n_prof, dtype=np.int32)
1586
+ sample_idx = np.arange(n_samp, dtype=np.int32)
1583
1587
 
1584
- # Direction per profile (down/up)
1585
- direction = None
1586
- if hasattr(self, 'DIR') and len(self.DIR) == n_prof:
1587
- direction = np.array(self.DIR, dtype=object)
1588
- else:
1589
- # Fallback based on even/odd
1590
- direction = np.array(['down' if i % 2 == 0 else 'up' for i in range(n_prof)], dtype=object)
1591
-
1592
- # Per-sample time as seconds since reference origin
1593
- # TIME_mvp is in days relative to self.date_ref
1594
- time_seconds = None
1595
- if hasattr(self, 'TIME_mvp'):
1596
- time_seconds = self.TIME_mvp * 24.0 * 3600.0
1597
- else:
1598
- time_seconds = np.full((n_prof, n_samp), np.nan)
1599
-
1600
- # Per-profile datetime (one timestamp per cast pair); map using i//2
1601
- profile_time = None
1602
- if hasattr(self, 'DATETIME_mvp') and len(getattr(self, 'DATETIME_mvp', [])) > 0:
1603
- prof_times = []
1604
- for i in range(n_prof):
1605
- j = i // 2
1606
- if j < len(self.DATETIME_mvp) and self.DATETIME_mvp[j] is not None:
1607
- prof_times.append(np.datetime64(self.DATETIME_mvp[j]))
1608
- else:
1609
- prof_times.append(np.datetime64('NaT'))
1610
- profile_time = np.array(prof_times, dtype='datetime64[ns]')
1611
- else:
1612
- profile_time = np.array([np.datetime64('NaT')] * n_prof, dtype='datetime64[ns]')
1588
+ # Direction per profile (down/up)
1589
+ direction = None
1590
+ if hasattr(self, 'DIR') and len(self.DIR) == n_prof:
1591
+ direction = np.array(self.DIR, dtype=object)
1592
+ else:
1593
+ # Fallback based on even/odd
1594
+ direction = np.array(['down' if i % 2 == 0 else 'up' for i in range(n_prof)], dtype=object)
1595
+
1596
+ # Per-sample time as seconds since reference origin
1597
+ # TIME_mvp is in days relative to self.date_ref
1598
+ time_seconds = None
1599
+ if hasattr(self, 'TIME_mvp'):
1600
+ time_seconds = self.TIME_mvp * 24.0 * 3600.0
1601
+ else:
1602
+ time_seconds = np.full((n_prof, n_samp), np.nan)
1603
+
1604
+ # Per-profile datetime (one timestamp per cast pair); map using i//2
1605
+ profile_time = None
1606
+ if hasattr(self, 'DATETIME_mvp') and len(getattr(self, 'DATETIME_mvp', [])) > 0:
1607
+ prof_times = []
1608
+ for i in range(n_prof):
1609
+ j = i // 2
1610
+ if j < len(self.DATETIME_mvp) and self.DATETIME_mvp[j] is not None:
1611
+ prof_times.append(np.datetime64(self.DATETIME_mvp[j]))
1612
+ else:
1613
+ prof_times.append(np.datetime64('NaT'))
1614
+ profile_time = np.array(prof_times, dtype='datetime64[ns]')
1615
+ else:
1616
+ profile_time = np.array([np.datetime64('NaT')] * n_prof, dtype='datetime64[ns]')
1613
1617
 
1614
- # Build dataset variables safely
1615
- data_vars = {}
1618
+ # Build dataset variables safely
1619
+ data_vars = {}
1616
1620
 
1617
- def add_var(var_name, arr, units=None, long_name=None):
1618
- if arr is None:
1619
- return
1620
- data_vars[var_name] = (
1621
- ('profile', 'sample'), arr,
1622
- {k: v for k, v in [('units', units), ('long_name', long_name)] if v is not None}
1623
- )
1624
-
1625
- add_var('PRES', getattr(self, 'PRES_mvp', None), units='dbar', long_name='Sea water pressure')
1626
- add_var('TEMP', getattr(self, 'TEMP_mvp', None), units='degC', long_name='In-situ temperature')
1627
- add_var('COND', getattr(self, 'COND_mvp', None), units='mS/cm', long_name='Conductivity')
1628
- add_var('SAL', getattr(self, 'SALT_mvp', None), units='psu', long_name='Practical salinity')
1629
- add_var('SOUNDVEL', getattr(self, 'SOUNDVEL_mvp', None), units='m s-1', long_name='Sound speed')
1630
- add_var('DO', getattr(self, 'DO_mvp', None), units='ml/L', long_name='Dissolved oxygen')
1631
- add_var('TEMP2', getattr(self, 'TEMP2_mvp', None), units='degC', long_name='Oxygen sensor temperature')
1632
- add_var('SUNA', getattr(self, 'SUNA_mvp', None), long_name='SUNA raw/derived')
1633
- add_var('FLUO', getattr(self, 'FLUO_mvp', None), units='ug/L', long_name='Chl fluorescence')
1634
- add_var('TURB', getattr(self, 'TURB_mvp', None), units='NTU', long_name='Turbidity')
1635
- add_var('PH', getattr(self, 'PH_mvp', None), units='1', long_name='pH')
1636
-
1637
- # Position and time arrays (2D)
1638
- if hasattr(self, 'LAT_mvp'):
1639
- add_var('LATITUDE', self.Lat_mvp, units='degrees_north', long_name='Latitude at sample')
1640
- if hasattr(self, 'LON_mvp'):
1641
- add_var('LONGITUDE', self.Lon_mvp, units='degrees_east', long_name='Longitude at sample')
1642
- # Time seconds since reference
1643
- data_vars['TIME'] = (
1644
- ('profile', 'sample'), time_seconds,
1645
- {
1646
- 'units': f'seconds since {self.date_ref.strftime("%Y-%m-%d %H:%M:%S")}',
1647
- 'long_name': 'Time at sample'
1648
- }
1621
+ def add_var(var_name, arr, units=None, long_name=None):
1622
+ if arr is None:
1623
+ return
1624
+ data_vars[var_name] = (
1625
+ ('profile', 'sample'), arr,
1626
+ {k: v for k, v in [('units', units), ('long_name', long_name)] if v is not None}
1649
1627
  )
1650
-
1651
- # Include corrected arrays if requested and present
1652
- if corrected:
1653
- def add_corr(name, attr, units=None, long_name=None):
1654
- if hasattr(self, attr):
1655
- data_vars[name] = (
1656
- ('profile', 'sample'), getattr(self, attr),
1657
- {k: v for k, v in [('units', units), ('long_name', long_name)] if v is not None}
1658
- )
1659
- add_corr('pressure_corrected', 'PRES_mvp_corr', units='dbar', long_name='Corrected pressure')
1660
- add_corr('temperature_corrected', 'TEMP_mvp_corr', units='degC', long_name='Corrected temperature')
1661
- add_corr('conductivity_corrected', 'COND_mvp_corr', units='mS/cm', long_name='Corrected conductivity')
1662
- add_corr('salinity_corrected', 'SALT_mvp_corr', units='psu', long_name='Corrected salinity')
1663
- if hasattr(self, 'TIME_mvp_corr'):
1664
- data_vars['time_corrected'] = (
1665
- ('profile', 'sample'), self.TIME_mvp_corr * 24.0 * 3600.0,
1666
- {
1667
- 'units': f'seconds since {self.date_ref.strftime("%Y-%m-%d %H:%M:%S")}',
1668
- 'long_name': 'Corrected time at sample'
1669
- }
1670
- )
1671
- if hasattr(self, 'LAT_mvp_corr'):
1672
- add_corr('latitude_corrected', 'LAT_mvp_corr', units='degrees_north', long_name='Corrected latitude at sample')
1673
- if hasattr(self, 'LON_mvp_corr'):
1674
- add_corr('longitude_corrected', 'LON_mvp_corr', units='degrees_east', long_name='Corrected longitude at sample')
1675
-
1676
- # Coordinates and auxiliary per-profile variables
1677
- coords = {
1678
- 'profile': ('profile', profile_idx),
1679
- 'sample': ('sample', sample_idx)
1628
+
1629
+ add_var('PRES', getattr(self, 'PRES_mvp', None), units='dbar', long_name='Sea water pressure')
1630
+ add_var('TEMP', getattr(self, 'TEMP_mvp', None), units='degC', long_name='In-situ temperature')
1631
+ add_var('COND', getattr(self, 'COND_mvp', None), units='mS/cm', long_name='Conductivity')
1632
+ add_var('SAL', getattr(self, 'SALT_mvp', None), units='psu', long_name='Practical salinity')
1633
+ add_var('SOUNDVEL', getattr(self, 'SOUNDVEL_mvp', None), units='m s-1', long_name='Sound speed')
1634
+ add_var('DO', getattr(self, 'DO_mvp', None), units='ml/L', long_name='Dissolved oxygen')
1635
+ add_var('TEMP2', getattr(self, 'TEMP2_mvp', None), units='degC', long_name='Oxygen sensor temperature')
1636
+ add_var('SUNA', getattr(self, 'SUNA_mvp', None), long_name='SUNA raw/derived')
1637
+ add_var('FLUO', getattr(self, 'FLUO_mvp', None), units='ug/L', long_name='Chl fluorescence')
1638
+ add_var('TURB', getattr(self, 'TURB_mvp', None), units='NTU', long_name='Turbidity')
1639
+ add_var('PH', getattr(self, 'PH_mvp', None), units='1', long_name='pH')
1640
+
1641
+ # Position and time arrays (2D)
1642
+ if hasattr(self, 'LAT_mvp'):
1643
+ add_var('LATITUDE', self.Lat_mvp, units='degrees_north', long_name='Latitude at sample')
1644
+ if hasattr(self, 'LON_mvp'):
1645
+ add_var('LONGITUDE', self.Lon_mvp, units='degrees_east', long_name='Longitude at sample')
1646
+ # Time seconds since reference
1647
+ data_vars['TIME'] = (
1648
+ ('profile', 'sample'), time_seconds,
1649
+ {
1650
+ 'units': f'seconds since {self.date_ref.strftime("%Y-%m-%d %H:%M:%S")}',
1651
+ 'long_name': 'Time at sample'
1680
1652
  }
1653
+ )
1681
1654
 
1682
- # Encode direction/time according to engine capabilities
1683
- if engine in ('netcdf4', 'h5netcdf'):
1684
- coords['direction'] = ('profile', direction.astype('U'), {'long_name': 'Profile direction'})
1685
- coords['profile_time'] = ('profile', profile_time, {'long_name': 'Profile nominal time'})
1686
- else:
1687
- # scipy backend: avoid object strings and datetime; use numeric fallbacks
1688
- dir_flag = np.where(direction.astype('U') == 'down', 0, 1).astype('int8')
1689
- coords['direction_flag'] = (
1690
- 'profile', dir_flag, {'long_name': 'Profile direction (0=down,1=up)'}
1691
- )
1692
- ref = np.datetime64(self.date_ref)
1693
- pt = profile_time.astype('datetime64[s]')
1694
- mask = (pt == np.datetime64('NaT'))
1695
- secs = (pt - ref).astype('timedelta64[s]').astype('float64')
1696
- secs[mask] = np.nan
1697
- coords['profile_time_sec'] = (
1698
- 'profile', secs,
1699
- {'units': f'seconds since {self.date_ref.strftime("%Y-%m-%d %H:%M:%S")}',
1700
- 'long_name': 'Profile nominal time'}
1701
- )
1702
-
1703
- # Optional per-profile lat/lon (first valid sample)
1704
- def first_valid(vec):
1705
- # vec shape (n_prof, n_samp)
1706
- out = np.full((vec.shape[0],), np.nan)
1707
- for i in range(vec.shape[0]):
1708
- row = vec[i]
1709
- j = np.where(~np.isnan(row))[0]
1710
- if j.size:
1711
- out[i] = row[j[0]]
1712
- return out
1713
-
1714
- if hasattr(self, 'LAT_mvp'):
1715
- coords['profile_lat'] = (
1716
- 'profile', first_valid(self.Lat_mvp), {'units': 'degrees_north', 'long_name': 'Profile latitude'}
1717
- )
1718
- if hasattr(self, 'LON_mvp'):
1719
- coords['profile_lon'] = (
1720
- 'profile', first_valid(self.Lon_mvp), {'units': 'degrees_east', 'long_name': 'Profile longitude'}
1655
+ # Include corrected arrays if requested and present
1656
+ if corrected:
1657
+ def add_corr(name, attr, units=None, long_name=None):
1658
+ if hasattr(self, attr):
1659
+ data_vars[name] = (
1660
+ ('profile', 'sample'), getattr(self, attr),
1661
+ {k: v for k, v in [('units', units), ('long_name', long_name)] if v is not None}
1662
+ )
1663
+ add_corr('pressure_corrected', 'PRES_mvp_corr', units='dbar', long_name='Corrected pressure')
1664
+ add_corr('temperature_corrected', 'TEMP_mvp_corr', units='degC', long_name='Corrected temperature')
1665
+ add_corr('conductivity_corrected', 'COND_mvp_corr', units='mS/cm', long_name='Corrected conductivity')
1666
+ add_corr('salinity_corrected', 'SALT_mvp_corr', units='psu', long_name='Corrected salinity')
1667
+ if hasattr(self, 'TIME_mvp_corr'):
1668
+ data_vars['time_corrected'] = (
1669
+ ('profile', 'sample'), self.TIME_mvp_corr * 24.0 * 3600.0,
1670
+ {
1671
+ 'units': f'seconds since {self.date_ref.strftime("%Y-%m-%d %H:%M:%S")}',
1672
+ 'long_name': 'Corrected time at sample'
1673
+ }
1721
1674
  )
1675
+ if hasattr(self, 'LAT_mvp_corr'):
1676
+ add_corr('latitude_corrected', 'LAT_mvp_corr', units='degrees_north', long_name='Corrected latitude at sample')
1677
+ if hasattr(self, 'LON_mvp_corr'):
1678
+ add_corr('longitude_corrected', 'LON_mvp_corr', units='degrees_east', long_name='Corrected longitude at sample')
1679
+
1680
+ # Coordinates and auxiliary per-profile variables
1681
+ coords = {
1682
+ 'profile': ('profile', profile_idx),
1683
+ 'sample': ('sample', sample_idx)
1684
+ }
1685
+
1686
+ # Encode direction/time according to engine capabilities
1687
+ if engine in ('netcdf4', 'h5netcdf'):
1688
+ coords['direction'] = ('profile', direction.astype('U'), {'long_name': 'Profile direction'})
1689
+ coords['profile_time'] = ('profile', profile_time, {'long_name': 'Profile nominal time'})
1690
+ else:
1691
+ # scipy backend: avoid object strings and datetime; use numeric fallbacks
1692
+ dir_flag = np.where(direction.astype('U') == 'down', 0, 1).astype('int8')
1693
+ coords['direction_flag'] = (
1694
+ 'profile', dir_flag, {'long_name': 'Profile direction (0=down,1=up)'}
1695
+ )
1696
+ ref = np.datetime64(self.date_ref)
1697
+ pt = profile_time.astype('datetime64[s]')
1698
+ mask = (pt == np.datetime64('NaT'))
1699
+ secs = (pt - ref).astype('timedelta64[s]').astype('float64')
1700
+ secs[mask] = np.nan
1701
+ coords['profile_time_sec'] = (
1702
+ 'profile', secs,
1703
+ {'units': f'seconds since {self.date_ref.strftime("%Y-%m-%d %H:%M:%S")}',
1704
+ 'long_name': 'Profile nominal time'}
1705
+ )
1722
1706
 
1723
- # Global attributes
1724
- attrs = {
1725
- 'title': 'MVP profile data',
1726
- 'Conventions': 'CF-1.8',
1727
- 'institution': 'LMD/CNRS',
1728
- 'source': 'PyMVP',
1729
- 'history': f"Created on {datetime.now().isoformat()}",
1730
- 'mvp_Yorig': int(self.Yorig)
1731
- }
1732
-
1733
- ds = xr.Dataset(data_vars=data_vars, coords=coords, attrs=attrs)
1707
+ # Optional per-profile lat/lon (first valid sample)
1708
+ def first_valid(vec):
1709
+ # vec shape (n_prof, n_samp)
1710
+ out = np.full((vec.shape[0],), np.nan)
1711
+ for i in range(vec.shape[0]):
1712
+ row = vec[i]
1713
+ j = np.where(~np.isnan(row))[0]
1714
+ if j.size:
1715
+ out[i] = row[j[0]]
1716
+ return out
1717
+
1718
+ if hasattr(self, 'LAT_mvp'):
1719
+ coords['profile_lat'] = (
1720
+ 'profile', first_valid(self.Lat_mvp), {'units': 'degrees_north', 'long_name': 'Profile latitude'}
1721
+ )
1722
+ if hasattr(self, 'LON_mvp'):
1723
+ coords['profile_lon'] = (
1724
+ 'profile', first_valid(self.Lon_mvp), {'units': 'degrees_east', 'long_name': 'Profile longitude'}
1725
+ )
1734
1726
 
1735
- # Compression encoding per engine
1736
- encoding = None
1737
- if compression:
1738
- if engine == 'netcdf4':
1739
- encoding = {name: {'zlib': True, 'complevel': 4} for name in data_vars.keys()}
1740
- elif engine == 'h5netcdf':
1741
- encoding = {name: {'compression': 'gzip', 'compression_opts': 4} for name in data_vars.keys()}
1727
+ # Global attributes
1728
+ attrs = {
1729
+ 'title': 'MVP profile data',
1730
+ 'Conventions': 'CF-1.8',
1731
+ 'institution': 'LMD/CNRS',
1732
+ 'source': 'PyMVP',
1733
+ 'history': f"Created on {datetime.now().isoformat()}",
1734
+ 'mvp_Yorig': int(self.Yorig)
1735
+ }
1736
+
1737
+ ds = xr.Dataset(data_vars=data_vars, coords=coords, attrs=attrs)
1738
+
1739
+ # Compression encoding per engine
1740
+ encoding = None
1741
+ if compression:
1742
+ if engine == 'netcdf4':
1743
+ encoding = {name: {'zlib': True, 'complevel': 4} for name in data_vars.keys()}
1744
+ elif engine == 'h5netcdf':
1745
+ encoding = {name: {'compression': 'gzip', 'compression_opts': 4} for name in data_vars.keys()}
1746
+
1747
+
1748
+ if (not per_profile_files) and filepath.lower().endswith('.nc'):
1749
+ out_path = filepath
1750
+ ds.to_netcdf(out_path, encoding=encoding, engine=engine)
1751
+ print(f"NetCDF written: {out_path} using engine={engine}")
1752
+ return
1753
+ base_dir = filepath
1754
+
1755
+ if not base_dir.endswith(os.sep):
1756
+ base_dir = base_dir + os.sep
1757
+
1758
+ base_name = "MVP_" + os.path.basename(self.data_path).rstrip(os.sep)
1759
+ if per_profile_files:
1760
+ # Write one file per pair (down/up)
1761
+ total_pairs = (n_prof + 1) // 2
1762
+ for i in range(total_pairs):
1763
+ idxs = [k for k in (2*i, 2*i+1) if k < n_prof]
1764
+ if not idxs:
1765
+ continue
1766
+ ds_i = ds.isel(profile=idxs)
1767
+
1768
+ #add i to filename
1769
+ fname = f"{base_name}_profile_{i:03d}.nc"
1770
+ out_path = os.path.join(base_dir, fname)
1771
+ ds_i.to_netcdf(out_path, encoding=encoding, engine=engine)
1772
+ print(f"NetCDF written per profile into: {base_dir} using engine={engine}")
1773
+ else:
1774
+ file_name = f"{base_name}.nc"
1775
+ out_path = os.path.join(base_dir, file_name)
1776
+ ds.to_netcdf(out_path, encoding=encoding, engine=engine)
1777
+ print(f"NetCDF written: {out_path} using engine={engine}")
1742
1778
 
1743
1779
 
1744
- if (not per_profile_files) and filepath.lower().endswith('.nc'):
1745
- out_path = filepath
1746
- ds.to_netcdf(out_path, encoding=encoding, engine=engine)
1747
- print(f"NetCDF written: {out_path} using engine={engine}")
1748
- return
1749
- base_dir = filepath
1750
-
1751
- if not base_dir.endswith(os.sep):
1752
- base_dir = base_dir + os.sep
1753
-
1754
- base_name = "MVP_" + os.path.basename(self.data_path).rstrip(os.sep)
1755
- if per_profile_files:
1756
- # Write one file per pair (down/up)
1757
- total_pairs = (n_prof + 1) // 2
1758
- for i in range(total_pairs):
1759
- idxs = [k for k in (2*i, 2*i+1) if k < n_prof]
1760
- if not idxs:
1761
- continue
1762
- ds_i = ds.isel(profile=idxs)
1763
-
1764
- #add i to filename
1765
- fname = f"{base_name}_profile_{i:03d}.nc"
1766
- out_path = os.path.join(base_dir, fname)
1767
- ds_i.to_netcdf(out_path, encoding=encoding, engine=engine)
1768
- print(f"NetCDF written per profile into: {base_dir} using engine={engine}")
1769
- else:
1770
- file_name = f"{base_name}.nc"
1771
- out_path = os.path.join(base_dir, file_name)
1772
- ds.to_netcdf(out_path, encoding=encoding, engine=engine)
1773
- print(f"NetCDF written: {out_path} using engine={engine}")
1774
-
1775
-
1776
- def help(self):
1777
- """
1778
- Print all methods of the class with their docstring (header).
1779
- """
1780
- for attr in dir(self):
1781
- if callable(getattr(self, attr)) and not attr.startswith("__"):
1782
- method = getattr(self, attr)
1783
- doc = method.__doc__
1784
- print(f"{attr}:\n{doc}\n{'-'*40}")
1780
+ def help(self):
1781
+ """
1782
+ Print all methods of the class with their docstring (header).
1783
+ """
1784
+ for attr in dir(self):
1785
+ if callable(getattr(self, attr)) and not attr.startswith("__"):
1786
+ method = getattr(self, attr)
1787
+ doc = method.__doc__
1788
+ print(f"{attr}:\n{doc}\n{'-'*40}")
1785
1789
 
1786
1790
 
1787
1791
  def plot_MVP_transect(self,var='TEMP',l_id=None,depth_max=None,depth_min=None,vmax=None,vmin=None,cmap=None):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyMVP
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: Python package for Moving Vessel Profiler correction and analysis
5
5
  Author: MaximilienWemaere
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "PyMVP"
3
- version = "0.2.4"
3
+ version = "0.2.5"
4
4
  description = "Python package for Moving Vessel Profiler correction and analysis"
5
5
  authors = [{name="MaximilienWemaere"}]
6
6
  readme = "README.md"
File without changes
File without changes
File without changes
File without changes
File without changes