diff --git a/ch_util/__init__.py b/ch_util/__init__.py index 417c8a72..2ed2ed50 100644 --- a/ch_util/__init__.py +++ b/ch_util/__init__.py @@ -7,16 +7,14 @@ .. autosummary:: :toctree: _autosummary - _db_tables andata cal_utils chan_monitor - connectdb - data_index data_quality ephemeris finder fluxcat + hfbcat holography layout ni_utils diff --git a/ch_util/andata.py b/ch_util/andata.py index 4c7aceb1..3947b7a4 100644 --- a/ch_util/andata.py +++ b/ch_util/andata.py @@ -2453,6 +2453,18 @@ def _prod_sel_from_stack_sel(stack_sel, stack_map, stack_rmap): def versiontuple(v): + """Create a version tuple from a version string. + + Parameters + ---------- + v: str + A version string + + Returns + ------- + versiontuple: tuple + A tuple of `int` values created by splitting the string on dots. + """ return tuple(map(int, (v.split(".")))) @@ -2900,6 +2912,36 @@ def _get_index_map_from_acq1(acq_files, time_sel, prod_sel, freq_sel): def andata_from_acq1(acq_files, start, stop, prod_sel, freq_sel, datasets, out_group): + """Create a `CorrData` object from a 1.0.0 archive version acq. + + Parameters + ---------- + acq_files : filename, `h5py.File` or list there-of or filename pattern + Files to convert from acquisition format to analysis format. + Filename patterns with wild cards (e.g. "foo*.h5") are supported. + start : int + What frame to start at in the full set of files. + stop : int + What frame to stop at in the full set of files. + prod_sel : 1D data selection + Valid numpy index for a 1D array, specifying what data to read + along the correlation product axis. + freq_sel : 1D data selection + Valid numpy index for a 1D array, specifying what data to read + along the frequency axis. + datasets : list of strings + Names of datasets to include from acquisition files. Default is to + include all datasets found in the acquisition files. + out_group : `h5py.Group`, hdf5 filename or `memh5.Group` + Underlying hdf5 like container that will store the data for the + BaseData instance. + + Returns + ------- + corrdata: + A `CorrData` object with the requested data. + """ + # First open all the files and collect necessary data for all of them. dtypes = _check_files_acq1(acq_files) # Figure how much of the total data to read. @@ -2976,6 +3018,38 @@ def andata_from_archive2( datasets, out_group, ): + """Create an Andata object from a version 2.0.0 archive format acq. + + Parameters + ---------- + cls: + class of object to create + acq_files : filename, `h5py.File` or list there-of or filename pattern + Files to convert from acquisition format to analysis format. + Filename patterns with wild cards (e.g. "foo*.h5") are supported. + start : int + What frame to start at in the full set of files. + stop : int + What frame to stop at in the full set of files. + prod_sel : 1D data selection + Valid numpy index for a 1D array, specifying what data to read + along the correlation product axis. + freq_sel : 1D data selection + Valid numpy index for a 1D array, specifying what data to read + along the frequency axis. + datasets : list of strings + Names of datasets to include from acquisition files. Default is to + include all datasets found in the acquisition files. + out_group : `h5py.Group`, hdf5 filename or `memh5.Group` + Underlying hdf5 like container that will store the data for the + BaseData instance. + + Returns: + ------- + andata : `cls` instance + The andata object for the requested data + """ + # XXX For short term force to CorrData class. Will be fixed once archive # files carry 'acquisition_type' attribute. # andata_objs = [ cls(d) for d in acq_files ] diff --git a/ch_util/fluxcat.py b/ch_util/fluxcat.py index cf7441f5..b70e8651 100644 --- a/ch_util/fluxcat.py +++ b/ch_util/fluxcat.py @@ -1307,6 +1307,19 @@ def load(cls, filename, overwrite=0, set_globals=False, verbose=False): def get_epoch(date): + """Return the epoch for a date. + + Parameters + ---------- + date : datetime.datetime + Date to calculate epoch + + Returns + ------- + epoch : float + The fractional-year epoch + """ + def sinceEpoch(date): # returns seconds since epoch return time.mktime(date.timetuple()) @@ -1322,6 +1335,22 @@ def sinceEpoch(date): # returns seconds since epoch def varname(name): + """Create a python variable name from `name`. + + The variable name replaces spaces in `name` with + underscores and adds a leading underscore if `name` + starts with a digit. + + Parameters + ---------- + name : str + The name to create a variable name for + + Returns + ------- + varname : str + The python variable name. + """ varname = name.replace(" ", "_") if varname[0].isdigit(): @@ -1331,6 +1360,17 @@ def varname(name): def format_source_name(input_name): + """Standardise the name of a source. + + Parameters + ---------- + input_name: str + The name to format + + Returns + formatted_name: str + The name after formatting. + """ # Address some common naming conventions. if input_name.startswith("NAME "): # SIMBAD prefixes common source names with 'NAME '. diff --git a/ch_util/layout.py b/ch_util/layout.py index ace97d09..19609b44 100644 --- a/ch_util/layout.py +++ b/ch_util/layout.py @@ -53,8 +53,7 @@ set component properties :meth:`component.set_property` :func:`set_property` get component properties :meth:`component.get_property` -make/sever many connexions and set many :func:`enter_ltf` -component properties at the same time +perform bulk updates :func:`enter_ltf` add component history notes :meth:`component.add_history` add link to component documentation :meth:`component.add_doc` create a global flag :meth:`global_flag.start` diff --git a/ch_util/tools.py b/ch_util/tools.py index d57cea39..d649aaaf 100644 --- a/ch_util/tools.py +++ b/ch_util/tools.py @@ -34,6 +34,7 @@ - :py:meth:`get_holographic_index` - :py:meth:`change_pathfinder_location` - :py:meth:`change_chime_location` +- :py:meth:`beam_index2number` This can determine if we are connected to any of the following: @@ -118,7 +119,6 @@ Miscellaneous ============= -- :py:meth:`invert_no_zero` - :py:meth:`ensure_list` """ @@ -1091,8 +1091,28 @@ def hk_to_sensor(graph, inp): return None -# Parse a serial number into crate, slot, and sma number def parse_chime_serial(sn): + """Parse a serial number into crate, slot, and SMA number. + + Parameters + ---------- + sn: str + Serial number to parse + + Returns + ------- + crate: int + Crate number + slot: int + Slot number + sma: int + SMA number + + Raises + ------ + RuntimeError: + `sn` did not have the correct format. + """ mo = re.match("FCC(\d{2})(\d{2})(\d{2})", sn) if mo is None: @@ -1108,6 +1128,27 @@ def parse_chime_serial(sn): def parse_pathfinder_serial(sn): + """Parse a pathfinder serial number into crate, slot, and SMA number. + + Parameters + ---------- + sn: str + Serial number to parse + + Returns + ------- + crate: int + Crate number + slot: int + Slot number + sma: int + SMA number + + Raises + ------ + RuntimeError: + `sn` did not have the correct format. + """ mo = re.match("(\w{6}\-\d{4})(\d{2})(\d{2})", sn) if mo is None: @@ -1123,6 +1164,25 @@ def parse_pathfinder_serial(sn): def parse_old_serial(sn): + """Parse an old 8/16-channel serial number into slot, and SMA number. + + Parameters + ---------- + sn: str + Serial number to parse + + Returns + ------- + slot: int + Slot number + sma: int + SMA number + + Raises + ------ + RuntimeError: + `sn` did not have the correct format. + """ mo = re.match("(\d{5}\-\d{4}\-\d{4})\-C(\d{1,2})", sn) if mo is None: @@ -1545,6 +1605,7 @@ def get_feed_positions(feeds, get_zpos=False): def fake_tone_database(): + """A fake correlator input database for GBO/TONE.""" positions_and_polarizations = [ ("S", [15.08, -1.61]), ("E", [15.08, -1.61]), @@ -2506,6 +2567,7 @@ def beam_index2number(beam_index): def invert_no_zero(*args, **kwargs): + """Deprecated - use 'caput.tools.invert_no_zero'""" from caput import tools import warnings diff --git a/doc/conf.py b/doc/conf.py index e339a01f..a89fe6f0 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -95,14 +95,14 @@ # General information about the project. project = "ch_util" -copyright = "2013, CHIME Collaboration" +copyright = "2013–2024, CHIME Collaboration" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = ch_util.__version__ +version = ".".join(ch_util.__version__.split(".")[:3]) # The full version, including alpha/beta/rc tags. release = ch_util.__version__