95 lines
3.2 KiB
Julia
95 lines
3.2 KiB
Julia
using Pkg
|
|
Pkg.activate("/app/environment")
|
|
|
|
# Handle dynamic environment fallback
|
|
if !haskey(Pkg.project().dependencies, "Plots")
|
|
Pkg.add("Plots")
|
|
end
|
|
|
|
ENV["GKSwstype"] = "100" # Headless rendering for Docker container
|
|
using Plots
|
|
|
|
# Load framework core dependencies smoothly
|
|
juliamsi_path = "/app/JuliaMSI"
|
|
push!(LOAD_PATH, joinpath(juliamsi_path, "src"))
|
|
include(joinpath(juliamsi_path, "src", "MSI_src.jl"))
|
|
using .MSI_src
|
|
|
|
using CSV, DataFrames
|
|
using Statistics
|
|
using Plots.Measures
|
|
|
|
# 1. PATH CONFIGURATIONS
|
|
data_path = "/app/data/Leaf.imzML"
|
|
mask_path = "/app/data/region_of_interest.png"
|
|
clusters_path = "/app/msi_clusters_results.csv"
|
|
|
|
println("Loading data arrays...")
|
|
data = OpenMSIData(data_path)
|
|
clusters_df = CSV.read(clusters_path, DataFrame)
|
|
|
|
# 2. RUN FRAMEWORK ANALYTICS TO DISCOVER PHYSICAL BOUNDARIES
|
|
println("Syncing Dataset Precomputed Boundaries...")
|
|
MSI_src.precompute_analytics(data)
|
|
|
|
# Extract binned spectrum arrays
|
|
mzs_avg, ints_avg = MSI_src.get_average_spectrum(data, mask_path=mask_path)
|
|
|
|
# --- DYNAMIC AXIS SAFEGUARD ---
|
|
# Query the atomic fields populated by precompute_analytics
|
|
# fallback to standard values if the fields return uninitialized values
|
|
min_vis_mz = data.global_min_mz[] > 0.0 ? data.global_min_mz[] : 50.0
|
|
max_vis_mz = data.global_max_mz[] > 0.0 ? data.global_max_mz[] : 700.0
|
|
|
|
println(" Detected Dynamic Min m/z Limit: ", round(min_vis_mz, digits=2))
|
|
println(" Detected Dynamic Max m/z Limit: ", round(max_vis_mz, digits=2))
|
|
|
|
# 3. Configure Base Plot Layer with Dynamic X-limits
|
|
p = plot(mzs_avg, ints_avg,
|
|
linecolor = :lightgray, # Light base so cluster sticks pop out visually
|
|
linewidth = 0.7,
|
|
label = "Average Spectrum (Reference)",
|
|
xlabel = "m/z",
|
|
ylabel = "Relative Intensity",
|
|
title = "Cluster Mapping on Isotopic Pattern",
|
|
size = (1200, 600),
|
|
legend = :outerright,
|
|
grid = false,
|
|
framestyle = :box,
|
|
xlims = (min_vis_mz, max_vis_mz), # Dynamically locks view strictly to valid mass range
|
|
left_margin = 15mm,
|
|
bottom_margin = 15mm
|
|
)
|
|
|
|
# 4. Use the exact qualitative 10-color palette seen in your image
|
|
cluster_colors = palette(:tab10)
|
|
|
|
# 5. Map Cluster Vectors to Binned Positions
|
|
println("Mapping chemical clusters onto binned coordinates...")
|
|
for cluster_id in sort(unique(clusters_df.cluster))
|
|
sub_df = filter(row -> row.cluster == cluster_id, clusters_df)
|
|
label_ready = false
|
|
|
|
for target_mz in sub_df.mz
|
|
# Find the closest matching bin channel index in the 2000-bin array
|
|
idx = argmin(abs.(mzs_avg .- target_mz))
|
|
|
|
m = mzs_avg[idx]
|
|
i = ints_avg[idx]
|
|
|
|
# Draw the vertical peak highlighter over the base spectrum
|
|
plot!(p, [m, m], [0, i],
|
|
linecolor = cluster_colors[cluster_id + 1],
|
|
linewidth = 1.2,
|
|
alpha = 0.9,
|
|
label = label_ready ? "" : "Cluster $cluster_id"
|
|
)
|
|
label_ready = true
|
|
end
|
|
end
|
|
|
|
# 6. Save assets to shared folder mount
|
|
savefig("/app/espectro_msi_paper_style.png")
|
|
println("Saved publication-ready plot: /app/espectro_msi_paper_style.png")
|
|
savefig("/app/espectro_msi_clusters_julia.png")
|
|
println("Saved backup copy: /app/espectro_msi_clusters_julia.png") |