### A Pluto.jl notebook ###
# v0.20.4

using Markdown
using InteractiveUtils

# ╔═╡ 635dcf78-b6b3-11ef-3a04-f5b7c43ed12d
begin
    using Pkg
    Pkg.activate(".")

    using PSBoardDataBase
    using SQLite
    using JLD2
    using DataFrames
    using CSV
    using CairoMakie
    using FHist
    using LinearAlgebra
    using Printf
    using PlutoUI
end

# ╔═╡ 3fccbdca-9856-4122-8597-9f267f90d390
md"""
# 説明
第6回 PS-Board QAQC キャンペーンの11_27のファームウェアを使った100回試験において、PLLLD fail countの数の分布の調査
"""

# ╔═╡ 3e844f3d-0017-41ae-9632-ae0f7e2b03f7
TableOfContents()

# ╔═╡ 26954da1-0820-490d-aa3e-79fd3603d28a
md"""
# データベース読み込み
"""

# ╔═╡ a36886af-ff32-4f4f-a20f-f83bc333b8fd
db = SQLite.DB("../psboard_qaqc.db")

# ╔═╡ df5087be-18de-4714-b6d8-4ab54271b1fb
SQLite.tables(db)

# ╔═╡ 566d3472-bd2d-489d-8736-857cb7ccaa93
jld2_slavelogs = jldopen("../slavelog.jld2")

# ╔═╡ 56d8896a-40e3-46e3-aa28-82f89476743b
qaqc_runs = DBInterface.execute(db, "select * from qaqc_runs") |> DataFrame

# ╔═╡ 08032250-5893-445c-8662-459e5636ba81
qaqc_extra_run_results =
    DBInterface.execute(db, "select * from qaqc_extra_run_results") |> DataFrame

# ╔═╡ 013948ff-ccde-4222-862b-7ecda62fd7f1
qaqc_extra_run_campaign_6 = let
    runids_campaign_6 = filter(:campaign_id => x -> (!ismissing(x) && x == 6), qaqc_runs).id
    filter(:runid => in(runids_campaign_6), qaqc_extra_run_results)
end

# ╔═╡ 0282181f-2607-43b6-8456-813c2636dabf
md"""
# 解析
"""

# ╔═╡ ecb09aa6-7f2e-4ef7-a081-348a219272e0
md"""
## PLLLD fail count
"""

# ╔═╡ 41da581f-0cdf-40f3-a1f8-bf1bd7f8835b
map(eachrow(qaqc_extra_run_campaign_6)) do row
    logfilename = "$(row.psboard_id)_$(row.runid)_longrun.txt"
    logfile = joinpath("../test/input/slavelogs/main/", logfilename)
    !ispath(logfile) && begin
        @info "file $(logfile) not found"
        return missing
    end
    slave_result = if haskey(jld2_slavelogs, logfilename)
        jld2_slavelogs[logfilename]
    else
        PSBoardDataBase.SlaveLogParser.parse_slavelog_file(logfile)
    end
    map(slave_result.asdtp) do asdtp_result
        asdtp_result.pllld_fail_counter
    end
end

# ╔═╡ 34ae2948-bb5a-4086-beb1-cfb77593d678
df_pllld_counts_camp6 = combine(
    groupby(qaqc_extra_run_campaign_6, :id),
    AsTable([:psboard_id, :runid]) =>
        (
            sdf -> begin
                @assert nrow(sdf) == 1
                logfilename = "$(sdf.psboard_id[1])_$(sdf.runid[1])_longrun.txt"
                logfile = joinpath("../test/input/slavelogs/main/", logfilename)
                !ispath(logfile) && begin
                    @warn "logfile $(logfile) not found"
                    return []
                end
                slave_result = if haskey(jld2_slavelogs, logfilename)
                    jld2_slavelogs[logfilename]
                else
                    PSBoardDataBase.SlaveLogParser.parse_slavelog_file(logfile)
                end
                return map(slave_result.asdtp) do asdtp_result
                    (
                        psboard_id = sdf.psboard_id[1],
                        runid = sdf.runid[1],
                        pllld_count = asdtp_result.pllld_fail_counter + 1,
                        reset_failed_though_reconfig_done = let
                            asdtp_result.reconfig_done_2 == 0 &&
                                asdtp_result.pllld_fail_counter == 10
                        end,
                    )
                end
            end
        ) => [:psboard_id, :runid, :pllld_count, :reset_failed_though_reconfig_done],
)

# ╔═╡ c084b8f4-dbc2-497b-9132-7e4bd4fd3874
sort(df_pllld_counts_camp6, :pllld_count, rev = true)

# ╔═╡ 6d85cc29-0d02-43b4-8a50-57f003e4686b
let
    df = combine(groupby(df_pllld_counts_camp6, :id), nrow)
    sort!(df, :nrow)
end

# ╔═╡ e95447c1-a8e2-4a46-9320-e1a88d9e34da
unique(df_pllld_counts_camp6.psboard_id) |> sort

# ╔═╡ 0433bbe4-1f71-4cf7-96ec-ac9c70170feb
stephist(df_pllld_counts_camp6.pllld_count)

# ╔═╡ f04d5c95-7308-4129-ba95-49da2e142d5d
let
    h1 = Hist1D(df_pllld_counts_camp6.pllld_count; binedges = 1:1:10, overflow = false)
    h1 = normalize(h1)
    fig = Figure()
    ax = Axis(
        fig[1, 1],
        yscale = log10,
        xlabel = "Number of resets before PLL lock",
        ylabel = "fraction",
        title = "PLLLD count ratios of 6th QAQC 100 test results",
    )
    stephist!(ax, h1, label = "pllld fail count")
    errorbars!(ax, h1)
    text!(
        ax,
        bincenters(h1),
        bincounts(h1),
        text = [@sprintf "%.4g" r for r in bincounts(h1)],
    )
    axislegend(position = :rt)
    Label(
        fig[1, 1],
        """
        n = $(nentries(h1))
        $(length(unique(df_pllld_counts_camp6.psboard_id))) PS-Boards
        """,
        tellwidth = false,
        tellheight = false,
        halign = :right,
        padding = (20, 20, 20, 20),
    )
    save("pllld_fail_counts.svg", fig)

    fig
end

# ╔═╡ 650482e5-9b79-4304-aa5a-2b7c9a377013
md"""
## "reconfig_done = 0なのにresetしていない" の数
"""

# ╔═╡ 4b9c0bd8-b17a-4933-8d6e-2da884fc4b5e
combine(
    groupby(df_pllld_counts_camp6, :id),
    AsTable(:) =>
        (
            sdf -> begin
                @assert allequal(sdf.psboard_id)
                @assert allequal(sdf.runid)
                (
                    reset_failed_though_reconfig_done = count(
                        sdf.reset_failed_though_reconfig_done,
                    ),
                    psboard_id = first(sdf.psboard_id),
                    runid = first(sdf.runid),
                )
            end
        ) => [:reset_failed_though_reconfig_done, :psboard_id, :runid],
)

# ╔═╡ a0baf37c-8b05-49c1-a6a4-027f3404f8b4
@time df_reset_failed_though_reconfig_done = let
    broken_list = filter(:is_slavelog_valid => !=(1), qaqc_extra_run_results)
    transform(
        qaqc_extra_run_results,
        [:psboard_id, :runid] =>
            ByRow(
                (psboard_id, runid) -> begin
                    if psboard_id in broken_list.psboard_id && runid in broken_list.runid
                        return (;
                            psboard_id,
                            runid,
                            reset_failed_though_reconfig_done = missing,
                        )
                    end

                    if runid == 99
                        @info "skipping runid 99 since it is not exactly 100 run"
                        return (
                            psboard_id = psboard_id,
                            runid = runid,
                            reset_failed_though_reconfig_done = missing,
                        )
                    end

                    logfilename = "$(psboard_id)_$(runid)_longrun.txt"
                    slave_result = if haskey(jld2_slavelogs, logfilename)
                        jld2_slavelogs[logfilename]
                    else
                        logfile = joinpath("../test/input/slavelogs/main/", logfilename)
                        PSBoardDataBase.SlaveLogParser.parse_slavelog_file(logfile)
                    end
                    return (
                        psboard_id = psboard_id,
                        runid = runid,
                        reset_failed_though_reconfig_done = count(
                            slave_result.asdtp,
                        ) do asdtp_result
                            asdtp_result.reconfig_done_2 != asdtp_result.reconfig_done
                        end,
                    )
                end,
            ) => [:psboard_id, :runid, :reset_failed_though_reconfig_done],
    )
end

# ╔═╡ 20633b30-a703-47bc-92a6-8743abbd375c
sort(
    dropmissing(df_reset_failed_though_reconfig_done, :reset_failed_though_reconfig_done),
    :reset_failed_though_reconfig_done,
    rev = true,
)

# ╔═╡ 9cf8e7cb-a1f6-4c5b-8c3b-3872d2020e57
result = PSBoardDataBase.SlaveLogParser.parse_slavelog_file(
    "../test/input/slavelogs/main/1070_310_longrun.txt",
)

# ╔═╡ 9b055b29-cf54-457d-8776-39430554ef9f
findall(result.asdtp) do result
    result.reconfig_done != result.reconfig_done_2
end

# ╔═╡ d5d479b5-4d55-4a55-aa5f-893141981838
result.asdtp[53]

# ╔═╡ 14519d45-a6a9-4ba1-a4f2-9597d1335b2c
let
    df_compare = outerjoin(
        df_reset_failed_though_reconfig_done,
        select(qaqc_extra_run_results, [:id, :reset_failed_though_reconfig_done]),
        on = :id,
        renamecols = "_old" => "_new",
    )
end

# ╔═╡ dfeb3900-539f-4d8d-8103-edb67cf4e890
# CSV.write(
#     "reset_failed_though_reconfig_done.csv",
#     df_reset_failed_though_reconfig_done[
#         :,
#         [:psboard_id, :runid, :reset_failed_though_reconfig_done],
#     ],
# )

# ╔═╡ 332b7481-f6dc-4027-a5c5-cf58d5b6acd3
md"""
## campaign 6 B-1-9 BCID failの分布
- PP ASICごとの分布 (全PS-Boardの和) 8 bins
- PP7のチャンネルごとの分布 32 bins
"""

# ╔═╡ 32f8a5b4-1027-48aa-a263-694515e582a2
asdtp_result_total_fail_vs_ppasic = let
    # B-1-9
    df = filter(:position => ==(18), qaqc_extra_run_campaign_6)

    asdtp_result_total_vs_ppasic = zeros(Int64, 8)
    for row in eachrow(df)
        slave_result =
            if haskey(jld2_slavelogs, "$(row.psboard_id)_$(row.runid)_longrun.txt")
                jld2_slavelogs["$(row.psboard_id)_$(row.runid)_longrun.txt"]
            else
                PSBoardDataBase.SlaveLogParser.parse_slavelog_file(
                    joinpath(
                        "../test/input/slavelogs/main/",
                        "$(row.psboard_id)_$(row.runid)_longrun.txt",
                    ),
                )
            end
        asdtp_results = slave_result.asdtp
        @assert length(asdtp_results) == 100
        # @info "" first(asdtp_results)
        ppasic_results = map(asdtp_results) do asdtp_result
            if ismissing(asdtp_result.asdtp_main)
                @info "missing" row.psboard_id row.runid
                return missing
            end
            map(asdtp_result.asdtp_main) do ppasic_result
                all(
                    ==(PSBoardDataBase.SlaveLogParser.AsdtpMeasurement(0.0, 1.0, 0.0)),
                    ppasic_result,
                )
            end
        end
        asdtp_result_vs_ppasic = map(1:8) do ppasic_id
            count(ppasic_results) do ppasic_result
                if ismissing(ppasic_result)
                    false
                else
                    ppasic_result[ppasic_id]
                end
            end
        end
        @info "" asdtp_result_vs_ppasic
        asdtp_result_total_vs_ppasic .+= (100 .- asdtp_result_vs_ppasic)
    end
    asdtp_result_total_vs_ppasic
end

# ╔═╡ 702fc37d-10e9-4495-b7a6-be1705747012
barplot(
    asdtp_result_total_fail_vs_ppasic,
    axis = (;
        xticks = (collect(1:8), ["PP$(id)" for id in 1:8]),
        xlabel = "PP ASIC",
        ylabel = "total number of BCID passed",
    ),
)

# ╔═╡ fc884334-fa09-40de-8a8d-1a31b8e28fca
md"""
- すべて PP 7
"""

# ╔═╡ 2d8eb86d-7545-484d-9209-0a10dcf93086
asdtp_result_total_pp7_vs_ch = let
    # B-1-9
    df = filter(:position => ==(18), qaqc_extra_run_campaign_6)

    asdtp_result_total_pp7_vs_ch = zeros(Int64, 32)
    for row in eachrow(df)
        slave_result =
            if haskey(jld2_slavelogs, "$(row.psboard_id)_$(row.runid)_longrun.txt")
                jld2_slavelogs["$(row.psboard_id)_$(row.runid)_longrun.txt"]
            else
                PSBoardDataBase.SlaveLogParser.parse_slavelog_file(
                    joinpath(
                        "../test/input/slavelogs/main/",
                        "$(row.psboard_id)_$(row.runid)_longrun.txt",
                    ),
                )
            end
        asdtp_results = slave_result.asdtp
        @assert length(asdtp_results) == 100
        # @info "" first(asdtp_results)
        ppasic7_ch_results = map(asdtp_results) do asdtp_result
            if ismissing(asdtp_result.asdtp_main)
                @info "missing" row.psboard_id row.runid
                return missing
            end

            map(asdtp_result.asdtp_main[7]) do ch_result
                ch_result == PSBoardDataBase.SlaveLogParser.AsdtpMeasurement(0.0, 1.0, 0.0)
            end
        end
        asdtp_result_ppasic7_vs_ch = map(1:32) do ch_id
            count(ppasic7_ch_results) do ppasic7_ch_result
                if ismissing(ppasic7_ch_result)
                    false
                else
                    ppasic7_ch_result[ch_id]
                end
            end
        end
        @info "" asdtp_result_ppasic7_vs_ch
        asdtp_result_total_pp7_vs_ch .+= (100 .- asdtp_result_ppasic7_vs_ch)
    end
    asdtp_result_total_pp7_vs_ch
end

# ╔═╡ 21eabebd-3514-4e2a-b0b5-84c74a051c68
barplot(
    asdtp_result_total_pp7_vs_ch,
    axis = (;
        title = "Campaign 7 B-1-9 PP ASIC7 BCID fail count vs channels",
        xlabel = "PP ASIC 7 ch id",
        ylabel = "total number of BCID passed",
    ),
)

# ╔═╡ Cell order:
# ╠═3fccbdca-9856-4122-8597-9f267f90d390
# ╠═635dcf78-b6b3-11ef-3a04-f5b7c43ed12d
# ╠═3e844f3d-0017-41ae-9632-ae0f7e2b03f7
# ╟─26954da1-0820-490d-aa3e-79fd3603d28a
# ╠═a36886af-ff32-4f4f-a20f-f83bc333b8fd
# ╠═df5087be-18de-4714-b6d8-4ab54271b1fb
# ╠═566d3472-bd2d-489d-8736-857cb7ccaa93
# ╠═56d8896a-40e3-46e3-aa28-82f89476743b
# ╠═08032250-5893-445c-8662-459e5636ba81
# ╠═013948ff-ccde-4222-862b-7ecda62fd7f1
# ╟─0282181f-2607-43b6-8456-813c2636dabf
# ╟─ecb09aa6-7f2e-4ef7-a081-348a219272e0
# ╠═41da581f-0cdf-40f3-a1f8-bf1bd7f8835b
# ╠═34ae2948-bb5a-4086-beb1-cfb77593d678
# ╠═c084b8f4-dbc2-497b-9132-7e4bd4fd3874
# ╠═6d85cc29-0d02-43b4-8a50-57f003e4686b
# ╠═e95447c1-a8e2-4a46-9320-e1a88d9e34da
# ╠═0433bbe4-1f71-4cf7-96ec-ac9c70170feb
# ╠═f04d5c95-7308-4129-ba95-49da2e142d5d
# ╟─650482e5-9b79-4304-aa5a-2b7c9a377013
# ╠═4b9c0bd8-b17a-4933-8d6e-2da884fc4b5e
# ╠═a0baf37c-8b05-49c1-a6a4-027f3404f8b4
# ╠═20633b30-a703-47bc-92a6-8743abbd375c
# ╠═9cf8e7cb-a1f6-4c5b-8c3b-3872d2020e57
# ╠═9b055b29-cf54-457d-8776-39430554ef9f
# ╠═d5d479b5-4d55-4a55-aa5f-893141981838
# ╠═14519d45-a6a9-4ba1-a4f2-9597d1335b2c
# ╠═dfeb3900-539f-4d8d-8103-edb67cf4e890
# ╟─332b7481-f6dc-4027-a5c5-cf58d5b6acd3
# ╠═32f8a5b4-1027-48aa-a263-694515e582a2
# ╠═702fc37d-10e9-4495-b7a6-be1705747012
# ╠═fc884334-fa09-40de-8a8d-1a31b8e28fca
# ╠═2d8eb86d-7545-484d-9209-0a10dcf93086
# ╠═21eabebd-3514-4e2a-b0b5-84c74a051c68
