Skip to content

Commit 522ac0b

Browse files
committed
compute rvs from ccfs
1 parent 4f1ff90 commit 522ac0b

File tree

1 file changed

+287
-0
lines changed

1 file changed

+287
-0
lines changed

examples/daily_rvs_v1.2.jl

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
verbose = true
2+
using Dates
3+
if verbose println(now()) end
4+
if verbose && !isdefined(Main,:RvSpectML) println("# Loading RvSpecML") end
5+
using RvSpectMLBase
6+
using EchelleCCFs
7+
using EchelleInstruments#, EchelleInstruments.NEID
8+
using RvSpectML
9+
if verbose println("# Loading NeidSolarScripts") end
10+
using SunAsAStar
11+
using NeidSolarScripts
12+
println("# Loading other packages 1/2")
13+
using ArgParse
14+
using Markdown
15+
16+
println("# Parsing arguments...")
17+
#lsf_width = 3.0e3
18+
function parse_commandline()
19+
s = ArgParseSettings( description = "Calculate RVs from JLD2 file with NEID's daily order CCFs.")
20+
#import_settings!(s, s_files_only, args_only=false)
21+
add_arg_group!(s, "Files", :argg_files)
22+
@add_arg_table! s begin
23+
"input"
24+
help = "Filename for input with daily order CCFs (jld2)"
25+
arg_type = String
26+
default = "daily_ccfs.jld2"
27+
"output"
28+
help = "Filename for output dailiy RVs (csv)"
29+
arg_type = String
30+
default = "daily_rvs.csv"
31+
"--overwrite"
32+
help = "Specify it's ok to overwrite the output file."
33+
#default = true
34+
action = :store_true
35+
end
36+
#=
37+
add_arg_group!(s, "CCF parameters", :argg_ccf_param)
38+
@add_arg_table! s begin
39+
"--orders_to_use"
40+
help = "First and last order _index_ to compute CCFs for"
41+
nargs = 2
42+
arg_type = Int64
43+
#default = [ min_order(NEID2D()), max_order(NEID2D()) ]
44+
#default = [ first(orders_to_use_default(NEID2D())), last(orders_to_use_default(NEID2D())) ]
45+
"--mask_scale_factor"
46+
help = "Specify CCF mask width scale as multiple of NEID default v width " * string(default_ccf_mask_v_width(NEID2D()))
47+
arg_type = Float64
48+
#default = round(lsf_width/default_ccf_mask_v_width(NEID2D()), sigdigits=3)
49+
"--line_width_50_default"
50+
help = "Specify default line full width half maximum"
51+
arg_type = Float64
52+
#default = 7.9e3 # m/2
53+
end
54+
=#
55+
add_arg_group!(s, "Algorithm more measuring RVs ", :argg_alg_param)
56+
@add_arg_table! s begin
57+
"--rv_alg"
58+
help = "Algorithm for measuring RVs."
59+
arg_type = String
60+
default = "template"
61+
#default = "gaussian"
62+
end
63+
add_arg_group!(s, "Filter manifest for ", :argg_filter_param)
64+
@add_arg_table! s begin
65+
"--target"
66+
help = "Target field"
67+
arg_type = String
68+
default = "Sun"
69+
"--datestr"
70+
help = "Filenames that contain date string."
71+
arg_type = String
72+
"--max_solar_hour_angle"
73+
help = "Maximum absolute value of solar hour angle."
74+
arg_type = Float64
75+
default = 3.12
76+
"--max_airmass"
77+
help = "Maximum airmass."
78+
arg_type = Float64
79+
default = 2.0
80+
"--min_expmeter"
81+
help = "Minimum exposure meter flux relative to model flux."
82+
arg_type = Float64
83+
default = 6e4
84+
#=
85+
"--min_expmeter_factor"
86+
help = "Minimum exposure meter flux relative to model flux."
87+
arg_type = Float64
88+
default = 0.9
89+
"--max_expmeter_factor"
90+
help = "Maximum exposure meter flux relative to model flux."
91+
arg_type = Float64
92+
default = 1.1
93+
=#
94+
"--max_expmeter_frac_rms"
95+
help = "Maximum fractional RMS of exposure meter flux."
96+
arg_type = Float64
97+
default = 0.01
98+
#=
99+
"--min_pyrhelio_factor"
100+
help = "Minimum pyrheliometer flux relative to model flux."
101+
arg_type = Float64
102+
default = 0.9
103+
"--max_pyrhelio_factor"
104+
help = "Maximum pyrheliometer flux relative to model flux."
105+
arg_type = Float64
106+
default = 1.1
107+
=#
108+
"--max_pyrhelio_frac_rms"
109+
help = "Maximum fractional RMS of pyrheliometer meter flux."
110+
arg_type = Float64
111+
default = 0.0035
112+
#=
113+
"--min_drp_snr"
114+
help = "Minimum extracted SNR reported by NEID DRP."
115+
arg_type = Float64
116+
#default = 0.0
117+
=#
118+
#=
119+
"--start_time"
120+
help = "Specify daily start time for CCFs to be processed (HH MM)"
121+
nargs = 2
122+
arg_type = Int64
123+
default = [0, 0]
124+
#default = [18, 30]
125+
"--stop_time"
126+
help = "Specify daily stop time for CCFs to be processed (HH MM)"
127+
nargs = 2
128+
arg_type = Int64
129+
#default = [ min_order(NEID2D()), max_order(NEID2D()) ]
130+
#default = [22, 30]
131+
default = [23, 59]
132+
=#
133+
"--max_num_spectra"
134+
help = "Maximum number of spectra to process."
135+
arg_type = Int
136+
default = 300 # TODO: Increase after finish testing
137+
end
138+
139+
return parse_args(s)
140+
end
141+
args = parse_commandline()
142+
@assert in(args["rv_alg"], ["template","gaussian","quadratic"] )
143+
144+
if verbose println("# Loading other packages 2/2") end
145+
using CSV, DataFrames, Query, Dates
146+
using JLD2, FileIO, MD5 #, SHA
147+
using StatsBase, Statistics, NaNMath
148+
149+
# Filename arguments
150+
@assert isfile(args["input"]) || islink(args["input"])
151+
@assert match(r"\.jld2$",args["input"]) != nothing
152+
daily_ccf_filename = args["input"]
153+
154+
args["overwrite"] = true # TODO: Comment after done testing
155+
if isfile(args["output"]) && !args["overwrite"]
156+
error("# Output file " * args["output"] * " already exists (size = " * string(filesize(args["output"])) * " ).")
157+
end
158+
@assert !isfile(args["output"]) || args["overwrite"]
159+
@assert match(r"\.csv$",args["output"]) != nothing
160+
daily_rvs_filename = args["output"]
161+
touch(daily_rvs_filename)
162+
163+
#=
164+
if isfile(args["report"]) && !args["overwrite"]
165+
error("# Report file " * args["report"] * " already exists (size = " * string(filesize(args["report"])) * " ).")
166+
end
167+
@assert !isfile(args["report"]) || args["overwrite"] == true
168+
@assert match(r"\.md$",args["report"]) != nothing
169+
daily_report_filename = args["report"]
170+
touch(daily_report_filename)
171+
=#
172+
173+
file_hashes = Dict{String,String}()
174+
start_processing_time = now()
175+
176+
if filesize(daily_ccf_filename) > 0
177+
println("# Reading daily CCFs from ", daily_ccf_filename)
178+
input_data = load(daily_ccf_filename)
179+
else
180+
println("# Empy daily CCF file. Creating empty ", daily_rvs_filename)
181+
touch(daily_rvs_filename)
182+
exit(0)
183+
end
184+
185+
println("# Filtering for usable observations...")
186+
manifest = input_data["manifest"]
187+
188+
manifest_use = manifest |>
189+
@filter( args["target"] == nothing || _.target == args["target"] ) |>
190+
@filter( args["datestr"] == nothing || occursin(args["datestr"],_.target) ) |>
191+
@filter( _.driftfun == "dailymodel0" ) |>
192+
@filter( args["max_airmass"] == nothing || _.airmass <= args["max_airmass"] ) |>
193+
@filter( args["max_solar_hour_angle"] == nothing || abs(_.solar_hour_angle) <= args["max_solar_hour_angle"] ) |>
194+
#@filter( args["start_time"] == nothing || Time(julian2datetime(_.bjd)) >= start_time ) |>
195+
#@filter( args["stop_time"] == nothing || Time(julian2datetime(_.bjd)) <= stop_time ) |> # TODO for other instruments may need to deal wtih cross end of 24 UTC
196+
@filter( args["min_expmeter"] == nothing || _.expmeter_mean >= args["min_expmeter"] ) |>
197+
DataFrame
198+
199+
if hasproperty(manifest_use,:mean_pyroflux) && hasproperty(manifest_use,:rms_pyroflux)
200+
manifest_use = manifest_use |>
201+
@filter( args["max_pyrhelio_frac_rms"] == nothing || _.rms_pyroflux <= args["max_pyrhelio_frac_rms"] * _.mean_pyroflux ) |>
202+
DataFrame
203+
else
204+
println("# Warning: mean_pyroflux and rms_pyroflux not found. Reverting to expmeter_mean and expmeter_rms.")
205+
manifest_use = manifest_use |>
206+
@filter( args["max_expmeter_frac_rms"] == nothing || _.expmeter_rms <= args["max_expmeter_frac_rms"] * _.expmeter_mean ) |>
207+
DataFrame
208+
end
209+
210+
manifest_use = manifest_use |>
211+
@take(args["max_num_spectra"] ) |> @orderby(_.bjd) |>
212+
DataFrame
213+
214+
#@assert size(manifest_use,1) >= 1
215+
if !(size(manifest_use,1) >= 1)
216+
println("# No usable observations. Creating empty ", daily_rvs_filename)
217+
touch(daily_rvs_filename)
218+
exit(0)
219+
end
220+
221+
println("# Found ", size(manifest_use,1), " files of ", size(manifest,1), " to use for RVs.")
222+
#df_out = manifest_use |> @rename(:drp_ccfjdmod=>:jd_drp,:drp_ccfrvmod => :rv_drp,:drp_dvrmsmod => :σrv_drp,
223+
df_out = manifest |> @rename(:drp_ccfjdmod=>:jd_drp,:drp_ccfrvmod => :rv_drp,:drp_dvrmsmod => :σrv_drp,
224+
:mean_pyroflux=>:pyrflux_mean, :rms_pyroflux=>:pyrflux_rms ) |> DataFrame
225+
obs_to_use = map(i->searchsortedfirst(manifest.bjd,manifest_use.bjd[i]),1:size(manifest_use,1) )
226+
227+
(num_vels, num_orders_to_use, num_obs) = size(input_data["order_ccfs"])
228+
229+
println("# Measuring RVs from RvSpectML's CCFs.")
230+
v_grid = collect(input_data["v_grid"])
231+
@assert num_vels == length(v_grid)
232+
order_ccfs = input_data["order_ccfs"]
233+
non_nan_mask = map(i->!any(isnan.(view(order_ccfs,:,:,i))), obs_to_use)
234+
obs_to_use = obs_to_use[non_nan_mask]
235+
mask = falses(1:num_obs)
236+
mask[obs_to_use] .= true
237+
df_out[!,"mask"] = mask
238+
239+
order_ccf_vars = input_data["order_ccf_vars"]
240+
ccf_sum = reshape(sum(order_ccfs,dims=2),num_vels,num_obs)
241+
ccf_var_sum = reshape(sum(input_data["order_ccf_vars"],dims=2),num_vels,num_obs)
242+
#rvs = measure_rv_from_ccf(v_grid,view(ccf_sum,:,1),view(ccf_var_sum,:,1))
243+
if args["rv_alg"] == "template"
244+
ccf_template = EchelleCCFs.calc_ccf_template(view(ccf_sum,:,obs_to_use), view(ccf_var_sum,:,obs_to_use) )
245+
alg_template = MeasureRvFromCCFTemplate(v_grid=collect(v_grid),template=ccf_template)
246+
rvs_template = DataFrame(map(i->measure_rv_from_ccf(v_grid,view(ccf_sum,:,i),view(ccf_var_sum,:,i),alg=alg_template),1:num_obs))
247+
df_out[!,Symbol("rv_template")] = rvs_template.rv
248+
df_out[!,Symbol("σrv_template")] = rvs_template.σ_rv
249+
elseif args["rv_alg"] == "gaussian"
250+
alg_gauss = MeasureRvFromCCFGaussian(frac_of_width_to_fit=0.25)
251+
rvs_gauss = DataFrame(map(i->measure_rv_from_ccf(v_grid,view(ccf_sum,:,i),view(ccf_var_sum,:,i),alg=alg_gauss),1:num_obs))
252+
df_out[!,Symbol("rv_gaussian")] = rvs_gauss.rv
253+
df_out[!,Symbol("σrv_gaussian")] = rvs_gauss.σ_rv
254+
elseif args["rv_alg"] == "quadratic"
255+
alg_quad = MeasureRvFromCCFQuadratic(frac_of_width_to_fit=0.25)
256+
rvs_quad = DataFrame(map(i->measure_rv_from_ccf(v_grid,view(ccf_sum,:,i),view(ccf_var_sum,:,i),alg=alg_quad),1:num_obs))
257+
df_out[!,Symbol("rv_quadratic")] = rvs_quad.rv
258+
df_out[!,Symbol("σrv_quadratic")] = rvs_quad.σ_rv
259+
end
260+
261+
orders_physical = collect(174 .-input_data["orders_to_use"])
262+
for j in 1:num_orders_to_use
263+
if iszero(maximum(view(order_ccfs,:,j,:))) || any(isnan.(view(order_ccfs,:,j,:))) continue end
264+
#println(" j = ", j, " order_fits_idx = ", input_data["orders_to_use"][j], " order_physical = ", orders_physical[j])
265+
if args["rv_alg"] == "template"
266+
# Templated-based
267+
local ccf_template = EchelleCCFs.calc_ccf_template(view(order_ccfs,:,j,obs_to_use), view(order_ccf_vars,:,j,obs_to_use) )
268+
local alg_template = MeasureRvFromCCFTemplate(v_grid=collect(v_grid),template=ccf_template)
269+
order_rvs_template = DataFrame(map(i->measure_rv_from_ccf(v_grid,view(order_ccfs,:,j,i),view(order_ccf_vars,:,j,i),alg=alg_template),1:num_obs))
270+
df_out[!,Symbol("rv_" * string(orders_physical[j]) * "_template")] = order_rvs_template.rv
271+
df_out[!,Symbol("σrv_" * string(orders_physical[j]) * "_template")] = order_rvs_template.σ_rv
272+
elseif args["rv_alg"] == "gaussian"
273+
# Gaussian fitting
274+
order_rvs_gauss = DataFrame(map(i->measure_rv_from_ccf(v_grid,view(order_ccfs,:,j,i),view(order_ccf_vars,:,j,i),alg=alg_gauss),1:num_obs))
275+
df_out[!,Symbol("rv_" * string(orders_physical[j]) * "_gauss")] = order_rvs_gauss.rv
276+
df_out[!,Symbol("σrv_" * string(orders_physical[j]) * "_gauss")] = order_rvs_gauss.σ_rv
277+
elseif args["rv_alg"] == "quadratic"
278+
# Quadratic fitting
279+
order_rvs_quad = DataFrame(map(i->measure_rv_from_ccf(v_grid,view(order_ccfs,:,j,i),view(order_ccf_vars,:,j,i),alg=alg_quad),1:num_obs))
280+
df_out[!,Symbol("rv_" * string(orders_physical[j]) * "_quad")] = order_rvs_quad.rv
281+
df_out[!,Symbol("σrv_" * string(orders_physical[j]) * "_quad")] = order_rvs_quad.σ_rv
282+
end
283+
end
284+
285+
println("# Writing daily RVs.")
286+
CSV.write(daily_rvs_filename,df_out)
287+

0 commit comments

Comments
 (0)