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.
- {pymvp-0.2.4 → pymvp-0.2.5}/PKG-INFO +1 -1
- {pymvp-0.2.4 → pymvp-0.2.5}/PyMVP/main.py +218 -214
- {pymvp-0.2.4 → pymvp-0.2.5}/PyMVP.egg-info/PKG-INFO +1 -1
- {pymvp-0.2.4 → pymvp-0.2.5}/pyproject.toml +1 -1
- {pymvp-0.2.4 → pymvp-0.2.5}/PyMVP/__init__.py +0 -0
- {pymvp-0.2.4 → pymvp-0.2.5}/PyMVP/mvp_routines.py +0 -0
- {pymvp-0.2.4 → pymvp-0.2.5}/PyMVP.egg-info/SOURCES.txt +0 -0
- {pymvp-0.2.4 → pymvp-0.2.5}/PyMVP.egg-info/dependency_links.txt +0 -0
- {pymvp-0.2.4 → pymvp-0.2.5}/PyMVP.egg-info/requires.txt +0 -0
- {pymvp-0.2.4 → pymvp-0.2.5}/PyMVP.egg-info/top_level.txt +0 -0
- {pymvp-0.2.4 → pymvp-0.2.5}/setup.cfg +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
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
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
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
|
-
|
|
1578
|
-
|
|
1581
|
+
# Dimensions
|
|
1582
|
+
n_prof, n_samp = self.PRES_mvp.shape
|
|
1579
1583
|
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
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
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
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
|
-
|
|
1615
|
-
|
|
1618
|
+
# Build dataset variables safely
|
|
1619
|
+
data_vars = {}
|
|
1616
1620
|
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
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
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
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
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
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
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
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
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
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
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
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):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|