Skip to content

Commit a496569

Browse files
Merge pull request #63 from CosmoStat/develop
v0.1.9
2 parents a9ccec3 + f8a9312 commit a496569

2 files changed

Lines changed: 71 additions & 78 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: 53 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import os
1212
from datetime import datetime
13+
1314
from importlib.metadata import version
1415
import numpy as np
1516
import healpy as hp
@@ -253,118 +254,93 @@ def read_dndz(file_path):
253254
254255
Returns
255256
-------
256-
list :
257+
np.array
257258
redshift bin centers
258-
list :
259+
np.array
259260
number densities
260-
list :
261-
redshift bin edges
261+
np.array
262+
redshift bin edges; one less than centers and density arrays
262263
263264
"""
264-
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")
265283

266-
# Remove last n(z) value which is zero, to match bin centers
267284
nz = dat["dn_dz"][:-1]
268285
z_edges = dat["z"]
286+
269287
z_centers = bin_edges2centers(z_edges)
270288

271289
return z_centers, nz, z_edges
272290

273291

274-
def read_hp_mask(input_name, verbose=False):
292+
def read_hp_mask(input_path, verbose=False):
275293
"""Read Hp Mask.
276294
277-
Read healpy mask.
295+
Read healpix mask FITS file.
278296
279-
Parameters
280-
----------
281-
input_name : str
282-
input file name
283-
verbose : bool, optional
284-
verbose output if ``True``;; default is ``False``
297+
Parameters
298+
----------
299+
input_path : str
300+
input file path
301+
verbose : bool, optional
302+
verbose output if ``True``; default is ``False``
285303
286-
Returns
287-
-------
288-
array
289-
mask values
290-
bool
291-
nest value (always ``False``)
292-
int
293-
nside
304+
Returns
305+
-------
306+
array
307+
mask information
308+
bool
309+
NEST (RING) ordering if ``True`` (``False``)
310+
int
311+
nside
294312
295313
"""
296314
if verbose:
297-
print(f'Reading mask {input_name}...')
315+
print(f"Reading mask {input_path}...")
298316

299317
nest = False
300318

301-
# Open input mask
302-
mask, header= hp.read_map(
303-
input_name,
319+
# Open input mask
320+
mask, header = hp.read_map(
321+
input_path,
304322
h=True,
305323
nest=nest,
306324
)
307-
for (key, value) in header:
308-
if key == 'ORDERING':
309-
if value == 'RING':
325+
for key, value in header:
326+
if key == "ORDERING":
327+
if value == "RING":
310328
if nest:
311329
raise ValueError(
312-
'input mask has ORDENING=RING, set nest to False'
330+
"input mask has ORDENING=RING, set nest to False"
313331
)
314-
elif value == 'NEST':
332+
elif value == "NEST":
315333
if not nest:
316334
raise ValueError(
317-
'input mask has ORDENING=NEST, set nest to True'
335+
"input mask has ORDENING=NEST, set nest to True"
318336
)
319337

320-
# Get nside from header
338+
# Get nside from header
321339
nside = None
322340
for key, value in header:
323-
if key == 'NSIDE':
341+
if key == "NSIDE":
324342
nside = int(value)
325343
if not nside:
326-
raise KeyError('NSIDE not found in FITS mask header')
344+
raise KeyError("NSIDE not found in FITS mask header")
327345

328346
return mask, nest, nside
329-
330-
331-
def get_binned_area(ra, dec, nside=512, return_pix=False):
332-
"""Get Binned Area.
333-
334-
Return sky area corresponding to occupied pixels of binned catalogue.
335-
336-
Parameters
337-
----------
338-
ra : np.ndarray
339-
Right Ascension coordinates
340-
dec : np.ndarray
341-
Declination coordinates
342-
nside : int, optional
343-
nside for binning; default is 512
344-
return_pix: bool, optional
345-
return valid pixel list if ``True``; default is ``False``
346-
347-
Returns
348-
-------
349-
float
350-
area in square degrees
351-
list
352-
pixels of input data positions
353-
354-
"""
355-
# Pixel list of input data
356-
pix = hp.ang2pix(nside, ra, dec, lonlat=True)
357-
358-
# Number of occupied pixels
359-
Nocc = np.unique(pix).size
360-
361-
# Pixel area in square degrees
362-
pix_area_deg2 = hp.nside2pixarea(nside, degrees=True)
363-
364-
# Footprint area in square degrees
365-
area_deg2 = Nocc * pix_area_deg2
366-
367-
if return_pix:
368-
return area_deg2, pix
369-
else:
370-
return area_deg2

0 commit comments

Comments
 (0)