Skip to content

Commit 3cd0a80

Browse files
Merge remote-tracking branch 'origin/main'
2 parents 75cc1d3 + a496569 commit 3cd0a80

5 files changed

Lines changed: 708 additions & 81 deletions

File tree

cs_util/args.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import sys
1111
import os
12+
import shlex
1213

1314
from optparse import OptionParser
1415

@@ -103,6 +104,9 @@ def my_string_split(string, num=-1, verbose=False, stop=False, sep=None):
103104
the first in the list [space, underscore] that occurs in the string.
104105
(Thus, if both occur, use space.)
105106
107+
Handles quoted strings: entries containing spaces can be enclosed
108+
in double quotes, e.g., 'value1 "entry with spaces" value3'.
109+
106110
Parameters
107111
----------
108112
string : str
@@ -131,6 +135,19 @@ def my_string_split(string, num=-1, verbose=False, stop=False, sep=None):
131135
if string is None:
132136
return None
133137

138+
# Handle quoted strings with shlex
139+
if '"' in string or "'" in string:
140+
try:
141+
res = shlex.split(string)
142+
if num != -1 and num != len(res) and stop:
143+
raise ValueError(
144+
f"String has {len(res)} elements, required is {num}"
145+
)
146+
return res
147+
except ValueError:
148+
# Fall through to regular splitting if shlex fails
149+
pass
150+
134151
if sep is None:
135152
has_space = string.find(" ")
136153
has_underscore = string.find("_")
@@ -162,7 +179,7 @@ def my_string_split(string, num=-1, verbose=False, stop=False, sep=None):
162179

163180
if num != -1 and num != len(res) and stop:
164181
raise ValueError(
165-
f"String '{len(res)}' has length {num}, required is {num}"
182+
f"String has {len(res)} elements, required is {num}"
166183
)
167184

168185
return res

cs_util/cat.py

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010

1111
import os
1212
from datetime import datetime
13+
1314
from importlib.metadata import version
15+
import numpy as np
16+
import healpy as hp
1417

1518
from astropy.io import fits
1619
from astropy.io import ascii
@@ -251,19 +254,93 @@ def read_dndz(file_path):
251254
252255
Returns
253256
-------
254-
list :
257+
np.array
255258
redshift bin centers
256-
list :
259+
np.array
257260
number densities
258-
list :
259-
redshift bin edges
261+
np.array
262+
redshift bin edges; one less than centers and density arrays
260263
261264
"""
262-
dat = ascii.read(file_path, format="commented_header")
265+
try:
266+
# Expecting header line "# z dn_dz"
267+
dat = ascii.read(file_path, format="commented_header")
268+
missing = [col for col in ("z", "dn_dz") if col not in dat.dtype.names]
269+
if missing:
270+
raise ValueError(
271+
f"Missing columns in dndz path {file_path}: {missing}"
272+
)
273+
except:
274+
# No header line
275+
dat = ascii.read(file_path)
276+
dat.rename_column("col1", "z")
277+
dat.rename_column("col2", "dn_dz")
278+
279+
# Remove last n(z) value which should be zero, to match bin centers
280+
tolerance = 1e-5
281+
if dat["dn_dz"][-1] / sum(dat["dn_dz"]) > tolerance:
282+
raise ValueError("dn_dz at last z-edge = {dat['dn_dz'][-1]}, no zero")
263283

264-
# Remove last n(z) value which is zero, to match bin centers
265284
nz = dat["dn_dz"][:-1]
266285
z_edges = dat["z"]
286+
267287
z_centers = bin_edges2centers(z_edges)
268288

269289
return z_centers, nz, z_edges
290+
291+
292+
def read_hp_mask(input_path, verbose=False):
293+
"""Read Hp Mask.
294+
295+
Read healpix mask FITS file.
296+
297+
Parameters
298+
----------
299+
input_path : str
300+
input file path
301+
verbose : bool, optional
302+
verbose output if ``True``; default is ``False``
303+
304+
Returns
305+
-------
306+
array
307+
mask information
308+
bool
309+
NEST (RING) ordering if ``True`` (``False``)
310+
int
311+
nside
312+
313+
"""
314+
if verbose:
315+
print(f"Reading mask {input_path}...")
316+
317+
nest = False
318+
319+
# Open input mask
320+
mask, header = hp.read_map(
321+
input_path,
322+
h=True,
323+
nest=nest,
324+
)
325+
for key, value in header:
326+
if key == "ORDERING":
327+
if value == "RING":
328+
if nest:
329+
raise ValueError(
330+
"input mask has ORDENING=RING, set nest to False"
331+
)
332+
elif value == "NEST":
333+
if not nest:
334+
raise ValueError(
335+
"input mask has ORDENING=NEST, set nest to True"
336+
)
337+
338+
# Get nside from header
339+
nside = None
340+
for key, value in header:
341+
if key == "NSIDE":
342+
nside = int(value)
343+
if not nside:
344+
raise KeyError("NSIDE not found in FITS mask header")
345+
346+
return mask, nest, nside

0 commit comments

Comments
 (0)