diff --git a/demerge/merge_function.py b/demerge/merge_function.py index bc9e52d..7bba603 100644 --- a/demerge/merge_function.py +++ b/demerge/merge_function.py @@ -18,7 +18,8 @@ 'Tlos_model', 'convert_readout', 'convert_asciitime', - 'convert_timestamp' + 'convert_timestamp', + 'update_corresp', ] @@ -31,10 +32,11 @@ # dependencies import numpy as np from astropy.io import fits, ascii +from astropy.io.fits import BinTableHDU from numpy.typing import NDArray -#-------------------------------- CONSTANTS +# constants FORM_FITSTIME = '%Y-%m-%dT%H:%M:%S' # YYYY-mm-ddTHH:MM:SS FORM_FITSTIME_P = '%Y-%m-%dT%H:%M:%S.%f' # YYYY-mm-ddTHH:MM:SS.ss @@ -42,6 +44,15 @@ DEFAULT_ROOM_T = 17. + 273. # Kelvin DEFAULT_AMB_T = 0. + 273. # Kelvin + +# constants (master-to-KID correspondence) +CORRESP_IGNORES = "pixelid", "runid, framelen, refid" +CORRESP_NOTFOUND = -1 +KIDFILT = "KIDFILT" +KIDID = "kidid" +MASTERID = "masterid" + + def create_bintablehdu(hd): """Create Binary Table HDU from 'hdu_dict'""" header = fits.Header() @@ -302,3 +313,29 @@ def retrieve_misti_log(filename): datetimes.append(datetime.strptime('{} {}'.format(row['date'], row['time']), '%Y/%m/%d %H:%M:%S.%f')) return (np.array(datetimes).astype('datetime64[ns]'), az, el, pwv) + + +def update_corresp(hdu: fits.BinTableHDU, corresp: dict[str, int]) -> BinTableHDU: + """Update the master-to-KID ID correspondence in an HDU. + + Args: + hdu: Binary Table HDU to be updated. + corresp: New master-to-KID ID correspondence. + + Returns: + (Copied) HDU with the new master-to-KID ID correspondence. + + """ + hdu_new = hdu.copy() + + for masterid, kidid in zip(hdu.data[MASTERID], hdu.data[KIDID]): + where = hdu_new.data[MASTERID] == masterid + + if (kidid_new := corresp.get(str(masterid))) is None: + for name in hdu_new.data.columns.names: + if name not in CORRESP_IGNORES: + hdu_new.data[name][where] = CORRESP_NOTFOUND + elif kidid_new != kidid: + hdu_new.data[KIDID][where] = kidid_new + + return hdu_new diff --git a/demerge/merge_to_dems.py b/demerge/merge_to_dems.py index 6c69393..b805978 100644 --- a/demerge/merge_to_dems.py +++ b/demerge/merge_to_dems.py @@ -7,6 +7,7 @@ """ # standard library import argparse +import json from logging import DEBUG, basicConfig, getLogger @@ -25,6 +26,7 @@ def merge_to_dems( ddbfits_path='', + corresp_path='', obsinst_path='', antenna_path='', readout_path='', @@ -55,13 +57,26 @@ def merge_to_dems( # その他一時的な補正 offset_time_antenna = kwargs.pop("offset_time_antenna", 0) # ms(integerでないとnp.timedeltaに変換できないので注意) - # 時刻と各種データを読み込む(必要に応じて時刻はnp.datetime64[ns]へ変換する) - readout_hdul = fits.open(readout_path) - ddbfits_hdul = fits.open(ddbfits_path) + # 時刻と各種データを読み込む + readout_hdul = fits.open(readout_path, mode="readonly") + ddbfits_hdul = fits.open(ddbfits_path, mode="readonly") weather_table = ascii.read(weather_path) antenna_table = ascii.read(antenna_path)[:-1] # 最後の1行は終端を表す意味のないデータが入っているため無視する obsinst_params = mf.load_obsinst(obsinst_path) # 観測スクリプトに含まれているパラメタを抽出する + # Update master-to-KID ID correspondences of HDUs + # (this should be done just after loading the DDB) + if corresp_path: + with open(corresp_path, mode="r") as f: + corresp = json.load(f) + + if (name := "KIDFILT") in ddbfits_hdul: + ddbfits_hdul[name] = mf.update_corresp(ddbfits_hdul[name], corresp) + + if (name := "KIDRESP") in ddbfits_hdul: + ddbfits_hdul[name] = mf.update_corresp(ddbfits_hdul[name], corresp) + + # 必要に応じて時刻はnp.datetime64[ns]へ変換する times = mf.convert_timestamp(readout_hdul['READOUT'].data['timestamp']) times = np.array(times).astype('datetime64[ns]') @@ -326,6 +341,7 @@ def main() -> None: # 必須引数 parser.add_argument('filename', type=str, help='出力ファイルへのパスを指定して下さい(.zarr.zip)') parser.add_argument('--ddb', type=str, required=True, help='DDBファイルへのパスを指定して下さい(.fits.gz)') + parser.add_argument('--corresp', type=str, required=True, help='Master-to-KID ID対応ファイルへのパスを指定して下さい(.json)') parser.add_argument('--obs', type=str, required=True, help='obsファイルへのパスを指定して下さい(.obs)') parser.add_argument('--antenna', type=str, required=True, help='antennaファイルへのパスを指定して下さい(.antenna)') parser.add_argument('--readout', type=str, required=True, help='reduced readoutファイルへのパスを指定して下さい(.fits)') @@ -372,6 +388,7 @@ def main() -> None: # マージの実行 dems = merge_to_dems( ddbfits_path=a.ddb, + corresp_path=a.corresp, obsinst_path=a.obs, antenna_path=a.antenna, readout_path=a.readout, diff --git a/demerge/run.sh b/demerge/run.sh index 28bfc49..3c8fa05 100755 --- a/demerge/run.sh +++ b/demerge/run.sh @@ -30,6 +30,7 @@ # -g グラフディレクトリを指定 # -d 観測データディレクトリの指定 # -b DDBファイルの指定 +# -i Master-to-KID ID対応ファイルの指定 # -o 出力データディレクトリの指定 # -m マージオプションの指定 # -p プロット実行オプションの指定 @@ -46,17 +47,19 @@ NCPU=`python -c "import multiprocessing as m; print(m.cpu_count() - 1);"` # -g グラフディレクトリを指定 # -d 観測データディレクトリの指定 # -b DDBファイルの指定 +# -i Master-to-KID ID対応ファイルの指定 # -o 出力データディレクトリの指定 # -m マージオプションの指定 # -p プロット実行オプションの指定 # -while getopts c:g:d:b:o:m:p: OPT +while getopts c:g:d:b:i:o:m:p: OPT do case $OPT in "c") CACHE_DIR="${OPTARG}";; "g") GRAPH_DIR="${OPTARG}";; "d") DATA_DIR="${OPTARG}";; "b") DDB_FILE="${OPTARG}";; + "i") CORRESP_FILE="${OPTARG}";; "o") OUT_DIR="${OPTARG}";; "m") MERGE_OPTS="${OPTARG}";; "p") PLOT="${OPTARG}";; @@ -83,6 +86,9 @@ fi if [ -z "$DDB_FILE" ]; then DDB_FILE="${DEFAULT_DDB}" # DDBファイルの既定値 fi +if [ -z "$CORRESP_FILE" ]; then + CORRESP_FILE="" # Master-to-KID ID対応ファイルの規定値 +fi if [ -z "$OUT_DIR" ]; then OUT_DIR="${CACHE_DIR}" # 出力ディレクトリの規定値 fi @@ -169,12 +175,13 @@ fi # # 引数(上から順に) # ================ -# caldb fitsファイルへの相対パス -# reduced fitsファイルへの相対パス +# DDBファイルへの相対パス +# Master-to-KID ID対応ファイルへの相対パス +# reduced readoutファイルへの相対パス # obsファイルへの相対パス -# antファイルへの相対パス +# antennaファイルへの相対パス # skychopファイルへの相対パス -# weaファイルへの相対パス +# weatherファイルへの相対パス # mistiファイルへの相対パス # cabinファイルへの相対パス # その他のmergeに関するオプション @@ -183,6 +190,7 @@ fi # merge_to_dems \ --ddb "${DDB_FILE}" \ + --corresp "${CORRESP_FILE}" \ --readout "${CACHE_DIR}/${OBSID}/reduced_${OBSID}.fits" \ --obs "${DATA_DIR}/cosmos_${OBSID}/${OBSID}.obs" \ --antenna "${DATA_DIR}/cosmos_${OBSID}/${OBSID}.ant" \