From c92576d5a5085ce5c015546e6b1a8bf474d6088e Mon Sep 17 00:00:00 2001 From: Pixelguy14 Date: Thu, 16 Jan 2025 16:22:32 -0600 Subject: [PATCH] Finished tabs and compare views, added file search to ease access to files, corrected minimal fixes --- Manifest.toml | 88 +++- Project.toml | 1 + app.jl | 880 ++++++++++++++++++----------------- app.jl.html | 92 ++-- public/css/autogenerated.css | 2 +- start_MSI_GUI.jl | 1 + 6 files changed, 589 insertions(+), 475 deletions(-) diff --git a/Manifest.toml b/Manifest.toml index 45acc6f..53bf45d 100644 --- a/Manifest.toml +++ b/Manifest.toml @@ -2,7 +2,13 @@ julia_version = "1.11.2" manifest_format = "2.0" -project_hash = "0eb77e47b715b07e9286c9a5bb8575a4c2a4963c" +project_hash = "e84343a015a9b60e7e39a0605149974e3d8cf1e0" + +[[deps.ATK_jll]] +deps = ["Artifacts", "Glib_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "a2ecb68d240333fe63bea1965b71884e98c2d0f0" +uuid = "7b86fcea-f67b-53e1-809c-8f1719c154e8" +version = "2.38.0+0" [[deps.AbstractFFTs]] deps = ["LinearAlgebra"] @@ -229,10 +235,10 @@ uuid = "944b1d66-785c-5afd-91f1-9de20f533193" version = "0.7.6" [[deps.ColorBrewer]] -deps = ["Colors", "JSON", "Test"] -git-tree-sha1 = "61c5334f33d91e570e1d0c3eb5465835242582c4" +deps = ["Colors", "JSON"] +git-tree-sha1 = "e771a63cc8b539eca78c85b0cabd9233d6c8f06f" uuid = "a2cac450-b92f-5266-8821-25eda20663c8" -version = "0.4.0" +version = "0.4.1" [[deps.ColorSchemes]] deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] @@ -647,6 +653,12 @@ git-tree-sha1 = "da121cbdc95b065da07fbb93638367737969693f" uuid = "d2c73de3-f751-5644-a686-071e5b155ba9" version = "0.72.8+0" +[[deps.GTK3_jll]] +deps = ["ATK_jll", "Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "FriBidi_jll", "Glib_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Libepoxy_jll", "Pango_jll", "Pkg", "Wayland_jll", "Xorg_libX11_jll", "Xorg_libXcomposite_jll", "Xorg_libXcursor_jll", "Xorg_libXdamage_jll", "Xorg_libXext_jll", "Xorg_libXfixes_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll", "Xorg_libXrender_jll", "at_spi2_atk_jll", "gdk_pixbuf_jll", "iso_codes_jll", "xkbcommon_jll"] +git-tree-sha1 = "b080a592525632d287aee4637a62682576b7f5e4" +uuid = "77ec8976-b24b-556a-a1bf-49a033a670a6" +version = "3.24.31+0" + [[deps.GarishPrint]] deps = ["Configurations", "Preferences"] git-tree-sha1 = "41136d24cc02c4d7c2b8c8982823fedac66d0a45" @@ -1213,6 +1225,12 @@ version = "1.11.0+1" uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" version = "1.11.0" +[[deps.Libepoxy_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libX11_jll"] +git-tree-sha1 = "7a0158b71f8be5c771e7a273183b2d0ac35278c5" +uuid = "42c93a91-0102-5b3f-8f9d-e41de60ac950" +version = "1.5.10+0" + [[deps.Libffi_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] git-tree-sha1 = "27ecae93dd25ee0909666e6835051dd684cc035e" @@ -1445,6 +1463,18 @@ git-tree-sha1 = "030ea22804ef91648f29b7ad3fc15fa49d0e6e71" uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" version = "1.0.3" +[[deps.NativeFileDialog]] +deps = ["FilePathsBase", "NativeFileDialog_jll"] +git-tree-sha1 = "6964c902c838b214cb4e8b4a94ca45e585c9d47b" +uuid = "e1fe445b-aa65-4df4-81c1-2041507f0fd4" +version = "0.2.1" + +[[deps.NativeFileDialog_jll]] +deps = ["Artifacts", "GTK3_jll", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "916d2db66748820c8e8bc3329a2a23c42c1520de" +uuid = "94d9ae2c-efc7-56f8-9a02-54c47b797961" +version = "1.1.6+3" + [[deps.NaturalSort]] git-tree-sha1 = "eda490d06b9f7c00752ee81cfa451efe55521e21" uuid = "c020b1a1-e9b0-503a-9c33-f039bfc54a85" @@ -1759,9 +1789,9 @@ uuid = "92933f4c-e287-5a05-a399-4b506db050ca" version = "1.10.2" [[deps.PtrArrays]] -git-tree-sha1 = "77a42d78b6a92df47ab37e177b2deac405e1c88f" +git-tree-sha1 = "1d36ef11a9aaf1e8b74dacc6a731dd1de8fd493d" uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" -version = "1.2.1" +version = "1.3.0" [[deps.PyCall]] deps = ["Conda", "Dates", "Libdl", "LinearAlgebra", "MacroTools", "Serialization", "VersionParsing"] @@ -2132,9 +2162,9 @@ weakdeps = ["DataFrames", "JSON", "OffsetArrays"] [[deps.StipplePivotTable]] deps = ["Stipple", "StippleUI", "Tables"] -git-tree-sha1 = "dcd4bb577152dd9945514e352d306a9dc89339a0" +git-tree-sha1 = "02c29d8464f1c26f659d1aa94d69a986ecaafea4" uuid = "adab0226-ee3c-44de-8f2f-393b1bf1e936" -version = "0.3.0" +version = "0.3.1" [[deps.StipplePlotly]] deps = ["DataFrames", "Genie", "Requires", "Stipple"] @@ -2408,12 +2438,24 @@ git-tree-sha1 = "e9216fdcd8514b7072b43653874fd688e4c6c003" uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec" version = "1.0.12+0" +[[deps.Xorg_libXcomposite_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll"] +git-tree-sha1 = "7c688ca9c957837539bbe1c53629bb871025e423" +uuid = "3c9796d7-64a0-5134-86ad-79f8eb684845" +version = "0.4.5+4" + [[deps.Xorg_libXcursor_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"] git-tree-sha1 = "807c226eaf3651e7b2c468f687ac788291f9a89b" uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724" version = "1.2.3+0" +[[deps.Xorg_libXdamage_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll"] +git-tree-sha1 = "fe4ffb2024ba3eddc862c6e1d70e2b070cd1c2bf" +uuid = "0aeada51-83db-5f97-b67e-184615cfc6f6" +version = "1.1.5+4" + [[deps.Xorg_libXdmcp_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] git-tree-sha1 = "89799ae67c17caa5b3b5a19b8469eeee474377db" @@ -2456,6 +2498,12 @@ git-tree-sha1 = "a490c6212a0e90d2d55111ac956f7c4fa9c277a6" uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa" version = "0.9.11+1" +[[deps.Xorg_libXtst_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll", "Xorg_libXi_jll"] +git-tree-sha1 = "0c0a60851f44add2a64069ddf213e941c30ed93c" +uuid = "b6f176f1-7aea-5357-ad67-1d3e565ea1c6" +version = "1.2.3+4" + [[deps.Xorg_libpthread_stubs_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] git-tree-sha1 = "c57201109a9e4c0585b208bb408bc41d205ac4e9" @@ -2539,12 +2587,36 @@ git-tree-sha1 = "622cf78670d067c738667aaa96c553430b65e269" uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" version = "1.5.7+0" +[[deps.at_spi2_atk_jll]] +deps = ["ATK_jll", "Artifacts", "JLLWrappers", "Libdl", "Pkg", "XML2_jll", "Xorg_libX11_jll", "at_spi2_core_jll"] +git-tree-sha1 = "f16ae690aca4761f33d2cb338ee9899e541f5eae" +uuid = "de012916-1e3f-58c2-8f29-df3ef51d412d" +version = "2.34.1+4" + +[[deps.at_spi2_core_jll]] +deps = ["Artifacts", "Dbus_jll", "Glib_jll", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXtst_jll"] +git-tree-sha1 = "d2d540cd145f2b2933614649c029d222fe125188" +uuid = "0fc3237b-ac94-5853-b45c-d43d59a06200" +version = "2.34.0+4" + [[deps.fzf_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] git-tree-sha1 = "6e50f145003024df4f5cb96c7fce79466741d601" uuid = "214eeab7-80f7-51ab-84ad-2988db7cef09" version = "0.56.3+0" +[[deps.gdk_pixbuf_jll]] +deps = ["Artifacts", "Glib_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pkg", "Xorg_libX11_jll", "libpng_jll"] +git-tree-sha1 = "e9190f9fb03f9c3b15b9fb0c380b0d57a3c8ea39" +uuid = "da03df04-f53b-5353-a52f-6a8b0620ced0" +version = "2.42.8+0" + +[[deps.iso_codes_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "d837a5d2a19d54243dafb6cc98d0f590a603dfa1" +uuid = "bf975903-5238-5d20-8243-bc370bc1e7e5" +version = "4.15.1+0" + [[deps.isoband_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] git-tree-sha1 = "51b5eeb3f98367157a7a12a1fb0aa5328946c03c" diff --git a/Project.toml b/Project.toml index 6d2d0fc..7105785 100644 --- a/Project.toml +++ b/Project.toml @@ -6,6 +6,7 @@ GenieFramework = "a59fdf5c-6bf0-4f5d-949c-a137c9e2f353" Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0" Libz = "2ec943e9-cfe8-584d-b93d-64dcb6d567b7" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +NativeFileDialog = "e1fe445b-aa65-4df4-81c1-2041507f0fd4" NaturalSort = "c020b1a1-e9b0-503a-9c33-f039bfc54a85" PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" diff --git a/app.jl b/app.jl index 13d2918..642d1f0 100644 --- a/app.jl +++ b/app.jl @@ -11,19 +11,20 @@ using Statistics using NaturalSort using Images using LinearAlgebra +using NativeFileDialog @genietools # == Code import == # add your data analysis code here or in the lib folder. Code in lib/ will be # automatically loaded -rgb_ViridisPalette = reinterpret(ColorTypes.RGB24, ViridisPalette) +rgb_ViridisPalette=reinterpret(ColorTypes.RGB24, ViridisPalette) # == Search functions == function increment_image(current_image, image_list) if isempty(image_list) return nothing end - current_index = findfirst(isequal(current_image), image_list) + current_index=findfirst(isequal(current_image), image_list) if current_index == nothing || current_index == length(image_list) || current_image === "" return image_list[length(image_list)] # Return the current image if it's the last one or not found else @@ -35,7 +36,7 @@ function decrement_image(current_image, image_list) if isempty(image_list) return nothing end - current_index = findfirst(isequal(current_image), image_list) + current_index=findfirst(isequal(current_image), image_list) if current_index == nothing || current_index == 1 || current_image === "" return image_list[1] # Return the current image if it's the first one or not found else @@ -51,118 +52,140 @@ end # @out variables can only be modified by the backend # @in variables can be modified by both the backend and the browser # variables must be initialized with constant values, or variables defined outside of the @app block - #@out test = "/test.bmp" #slash means it's getting the info from 'public' folder + #@out test="/test.bmp" #slash means it's getting the info from 'public' folder # Interface non Variables - @out warning_fr = "" - @out btnStartDisable = true - @out btnPlotDisable = true - @in warning_msg = false - @in CompareDialog = false + @out warning_fr="" + @out btnStartDisable=true + @out btnPlotDisable=false + @in warning_msg=false + @in CompareDialog=false # Interface Variables - @in file_route = "" - @in file_name = "" - @in Nmass = 0.0 - @in Tol = 0.0 - @in triqProb = 0.98 - @in triqColor = 256 + @in file_route="" + @in file_name="" + @in Nmass=0.0 + @in Tol=0.0 + @in triqProb=0.98 + @in triqColor=256 # Interface Buttons - @in mainProcess = false # To generate images - @in CompareBtn = false # to open dialog - @in createSumPlot = false # To generate sum spectrum plot - @in image3dPlot = false # To generate 3d plot based on current image - @in triq3dPlot = false # To generate 3d plot based on current triq image - @in imageCPlot = false # To generate contour plots of current image - @in triqCPlot = false # To generate contour plots of current triq image - @in progress = false - @in progressPlot = false - @in triqEnabled = false - @in ImgPlus = false - @in ImgMinus = false - @in ImgPlusT = false - @in ImgMinusT = false + @in btnSearch=false # To search for files in your device + @in mainProcess=false # To generate images + @in CompareBtn=false # to open dialog + @in createSumPlot=false # To generate sum spectrum plot + @in image3dPlot=false # To generate 3d plot based on current image + @in triq3dPlot=false # To generate 3d plot based on current triq image + @in imageCPlot=false # To generate contour plots of current image + @in triqCPlot=false # To generate contour plots of current triq image + @in progress=false + @in progressPlot=false + @in triqEnabled=false + @in ImgPlus=false + @in ImgMinus=false + @in ImgPlusT=false + @in ImgMinusT=false #TABS - @out tabIDs = ["tab0","tab1","tab2","tab3"] - @out tabLabels = ["Image", "TrIQ", "2D Plot","3D Plot"] - @in selectedTab = "tab0" + @out tabIDs=["tab0","tab1","tab2","tab3","tab4"] + @out tabLabels=["Image", "TrIQ", "Spectrum Plot", "Topology Plot","Surface Plot"] + @in selectedTab= "tab0" + @out CompTabIDs=["tab0","tab1","tab2","tab3","tab4"] + @out CompTabLabels=["Image", "TrIQ", "Spectrum Plot", "Topology Plot","Surface Plot"] + @in CompSelectedTab= "tab0" # Interface Images - @out imgInt = "/.bmp" # image Interface - @out imgIntT = "/.bmp" # image Interface TrIQ - @out colorbar = "/.png" - @out colorbarT = "/.png" + @out imgInt="/.bmp" # image Interface + @out imgIntT="/.bmp" # image Interface TrIQ + @out colorbar="/.png" + @out colorbarT="/.png" - @out msg = "" - @out msgimg = "" - @out msgtriq = "" + @out msg="" + @out msgimg="" + @out msgtriq="" - @out full_route = "" - @out full_routeMz = "" - @out full_routeMz2 = "" + @out full_route="" + @out full_routeMz="" + @out full_routeMz2="" # For the creation of images with a more specific mass charge - @out text_nmass = "" + @out text_nmass="" # For image search # Image lists we apply a filter that searches specific type of images into our public folder, then we sort it in a "numerical" order - @in msi_bmp = sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) - @in col_msi_png = sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) - @in triq_bmp = sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) - @in col_triq_png = sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) + @in msi_bmp=sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + @in col_msi_png=sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) + @in triq_bmp=sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + @in col_triq_png=sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) # Set current image for the list - @out current_msi = "" - @out current_col_msi = "" - @out current_triq = "" - @out current_col_triq = "" + @out current_msi="" + @out current_col_msi="" + @out current_triq="" + @out current_col_triq="" - @out indeximg = 0 - @out indeximgTriq = 0 + @out indeximg=0 + @out indeximgTriq=0 - @out lastimg = 0 - @out lastimgTriq = 0 + @out lastimg=0 + @out lastimgTriq=0 - # Interface Plot 2d - layoutSpectra = PlotlyBase.Layout( - title = "SUM Spectrum plot", - xaxis = PlotlyBase.attr( - title = "m/z", - showgrid = true + # Interface Plot Spectrum + layoutSpectra=PlotlyBase.Layout( + title="SUM Spectrum plot", + xaxis=PlotlyBase.attr( + title="m/z", + showgrid=true ), - yaxis = PlotlyBase.attr( - title = "Intensity", - showgrid = true + yaxis=PlotlyBase.attr( + title="Intensity", + showgrid=true ) ) # Dummy 2D surface plot - traceSpectra = PlotlyBase.scatter(x=[], y=[], mode="lines") + traceSpectra=PlotlyBase.scatter(x=[], y=[], mode="lines") # Create conection to frontend - @out plotdata = [traceSpectra] - @out plotlayout = layoutSpectra + @out plotdata=[traceSpectra] + @out plotlayout=layoutSpectra + + # Interface Plot Surface + layoutContour=PlotlyBase.Layout( + title="2D Topographic Map", + xaxis=PlotlyBase.attr( + title="X", + showgrid=true + ), + yaxis=PlotlyBase.attr( + title="Y", + showgrid=true + ) + ) + # Dummy 2D surface plot + traceContour=PlotlyBase.scatter(x=[], y=[], mode="lines") + # Create conection to frontend + @out plotdataC=[traceContour] + @out plotlayoutC=layoutContour # Interface Plot 3d # Define the layout for the 3D plot - layout3D = PlotlyBase.Layout( - title = "3D Surface Plot", - scene = attr( - xaxis_title = "X", - yaxis_title = "Y", - zaxis_title = "Z", - xaxis_nticks = 20, - yaxis_nticks = 20, - zaxis_nticks = 4, - camera = attr(eye = attr(x = 0, y = -1, z = 0.5)), - aspectratio = attr(x = 1, y = 1, z = 0.2) + layout3D=PlotlyBase.Layout( + title="3D Surface Plot", + scene=attr( + xaxis_title="X", + yaxis_title="Y", + zaxis_title="Z", + xaxis_nticks=20, + yaxis_nticks=20, + zaxis_nticks=4, + camera=attr(eye=attr(x=0, y=-1, z=0.5)), + aspectratio=attr(x=1, y=1, z=0.2) ) ) # Dummy 3D surface plot - x = 1:10 - y = 1:10 - z = [sin(i * j / 10) for i in x, j in y] - trace3D = PlotlyBase.surface(x=[], y=[], z=[], + x=1:10 + y=1:10 + z=[sin(i * j / 10) for i in x, j in y] + trace3D=PlotlyBase.surface(x=[], y=[], z=[], contours_z=attr( show=true, usecolormap=true, @@ -170,566 +193,571 @@ end project_z=true ), colorscale="Viridis") # Create conection to frontend - @out plotdata3d = [trace3D] - @out plotlayout3d = layout3D + @out plotdata3d=[trace3D] + @out plotlayout3d=layout3D # println("3D trace defined: ", trace3D) # == Reactive handlers == # Reactive handlers watch a variable and execute a block of code when its value changes # The onbutton handler will set the variable to false after the block is executed - - @onchange file_name begin - msg = "" - progress = false - progressPlot = false - try - if contains(file_name,".imzML") - warning_fr = "" - full_route = joinpath( file_route, file_name ) - if isfile(full_route) # Check if the file exists - btnPlotDisable = false - btnStartDisable = false - else - warning_fr = "is not an imzML file" - end - else - btnPlotDisable = true - btnStartDisable = true - full_route = "/" - warning_fr = "is not an imzML or mzML file" - end - catch e - msg = "There was an error, please verify the file and try again. $(e)" + + @onbutton btnSearch begin + full_route=pick_file(; filterlist="imzML") + if isnothing(full_route) + #println("No file selected") + msg="No file selected" + warning_msg=true + btnStartDisable=true + else + #println("Selected file path: ", full_route) + btnStartDisable=false + btnPlotDisable=false + msi_bmp=sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + col_msi_png=sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) + triq_bmp=sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + col_triq_png=sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) end end + """ @onchange Nmass begin - indeximg = floor(Int, Nmass) - indeximgTriq = floor(Int, Nmass) - lastimg = floor(Int, Nmass) - lastimgTriq = floor(Int, Nmass) + indeximg=floor(Int, Nmass) + indeximgTriq=floor(Int, Nmass) + lastimg=floor(Int, Nmass) + lastimgTriq=floor(Int, Nmass) end """ @onbutton mainProcess begin - progress = true # Start progress button animation - btnStartDisable = true # We disable the button to avoid multiple requests - indeximg = floor(Int, Nmass) - text_nmass = replace(string(Nmass), "." => "_") - full_route = joinpath(file_route, file_name) + progress=true # Start progress button animation + btnStartDisable=true # We disable the button to avoid multiple requests + btnPlotDisable=true + indeximg=floor(Int, Nmass) + text_nmass=replace(string(Nmass), "." => "_") + #full_route=joinpath(file_route, file_name) if isfile(full_route) && Nmass > 0 && Tol > 0 && Tol <= 1 - msg = "File exists, Nmass=$(Nmass) Tol=$(Tol). Loading file will begin, please be patient." + msg="File exists, Nmass=$(Nmass) Tol=$(Tol). Loading file will begin, please be patient." try - spectra = LoadImzml(full_route) - msg = "File loaded. Creating Spectra with the specific mass and tolerance, please be patient." - slice = GetSlice(spectra, Nmass, Tol) - fig = CairoMakie.Figure(size = (100, 200)) # Container + spectra=LoadImzml(full_route) + msg="File loaded. Creating Spectra with the specific mass and tolerance, please be patient." + slice=GetSlice(spectra, Nmass, Tol) + fig=CairoMakie.Figure(size=(100, 200)) # Container # Append a query string to force the image to refresh - timestamp = string(time_ns()) + timestamp=string(time_ns()) if triqEnabled # If we have TrIQ if triqColor < 1 || triqColor > 256 ||triqProb < 0 || triqProb > 1 - msg = "Incorrect TrIQ values, please adjust accordingly and try again." - warning_msg = true + msg="Incorrect TrIQ values, please adjust accordingly and try again." + warning_msg=true else - image_path = joinpath("./public", "TrIQ_$(text_nmass).bmp") + image_path=joinpath("./public", "TrIQ_$(text_nmass).bmp") SaveBitmap(joinpath("public", "TrIQ_$(text_nmass).bmp"),TrIQ(slice, Int(triqColor), triqProb),ViridisPalette) # Flip te image vertically then save it again - img = load(image_path) + img=load(image_path) if size(img, 1) > size(img, 2) # fix to taller images - img = reverse(permutedims(img, (2, 1)), dims=1) + img=reverse(permutedims(img, (2, 1)), dims=1) end - flipped_img = reverse(img, dims=1) + flipped_img=reverse(img, dims=1) save(image_path, flipped_img) # Use timestamp to refresh image interface container - imgIntT = "/TrIQ_$(text_nmass).bmp?t=$(timestamp)" + imgIntT="/TrIQ_$(text_nmass).bmp?t=$(timestamp)" # Get current image - current_triq = "TrIQ_$(text_nmass).bmp" - msgtriq = "TrIQ image with the Nmass of $(replace(text_nmass, "_" => "."))" + current_triq="TrIQ_$(text_nmass).bmp" + msgtriq="TrIQ image with the Nmass of $(replace(text_nmass, "_" => "."))" # Create colorbar - ticks = round.(range(0, stop = maximum(TrIQ(slice, Int(triqColor), triqProb)), length = 10), digits = 2) - Colorbar(fig[1, 1], colormap = rgb_ViridisPalette, limits = (0, maximum(TrIQ(slice, Int(triqColor), triqProb))),ticks = ticks, label = "Intensity") + ticks=round.(range(0, stop=maximum(TrIQ(slice, Int(triqColor), triqProb)), length=10), digits=2) + Colorbar(fig[1, 1], colormap=rgb_ViridisPalette, limits=(0, maximum(TrIQ(slice, Int(triqColor), triqProb))),ticks=ticks, label="Intensity") save("public/colorbar_TrIQ_$(text_nmass).png", fig) - colorbarT = "/colorbar_TrIQ_$(text_nmass).png?t=$(timestamp)" + colorbarT="/colorbar_TrIQ_$(text_nmass).png?t=$(timestamp)" # Get current colorbar - current_col_triq = "colorbar_TrIQ_$(text_nmass).png" + current_col_triq="colorbar_TrIQ_$(text_nmass).png" # We update the directory to include the new placed images. - triq_bmp = sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) - col_triq_png = sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) - - msg = "The file has been created successfully inside the 'public' folder of the app." - #println("all msi in folder = ",triq_bmp) + triq_bmp=sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + col_triq_png=sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) + msg="The file has been created successfully inside the 'public' folder of the app." + selectedTab="tab1" + #println("all msi in folder=",triq_bmp) #println("all col msi in folder= ",col_triq_png) end else # If we don't use TrIQ - image_path = joinpath("./public", "MSI_$(text_nmass).bmp") + image_path=joinpath("./public", "MSI_$(text_nmass).bmp") SaveBitmap(joinpath("public", "MSI_$(text_nmass).bmp"),IntQuant(slice),ViridisPalette) # Flip te image vertically then save it again - img = load(image_path) + img=load(image_path) if size(img, 1) > size(img, 2) # fix to taller images - img = reverse(permutedims(img, (2, 1)), dims=1) + img=reverse(permutedims(img, (2, 1)), dims=1) end - flipped_img = reverse(img, dims=1) + flipped_img=reverse(img, dims=1) save(image_path, flipped_img) # Use timestamp to refresh image interface container - imgInt = "/MSI_$(text_nmass).bmp?t=$(timestamp)" + imgInt="/MSI_$(text_nmass).bmp?t=$(timestamp)" # Get current image - current_msi = "MSI_$(text_nmass).bmp" - msgimg = "image with the Nmass of $(replace(text_nmass, "_" => "."))" + current_msi="MSI_$(text_nmass).bmp" + msgimg="Image with the Nmass of $(replace(text_nmass, "_" => "."))" # Create colorbar - ticks = round.(range(0, stop = maximum(slice), length = 10), digits = 2) - Colorbar(fig[1, 1], colormap = rgb_ViridisPalette, limits = (0, maximum(slice)),ticks = ticks, label = "Intensity") + ticks=round.(range(0, stop=maximum(slice), length=10), digits=2) + Colorbar(fig[1, 1], colormap=rgb_ViridisPalette, limits=(0, maximum(slice)),ticks=ticks, label="Intensity") save("public/colorbar_MSI_$(text_nmass).png", fig) - colorbar = "/colorbar_MSI_$(text_nmass).png?t=$(timestamp)" + colorbar="/colorbar_MSI_$(text_nmass).png?t=$(timestamp)" # Get current colorbar - current_col_msi = "colorbar_MSI_$(text_nmass).png" + current_col_msi="colorbar_MSI_$(text_nmass).png" # We update the directory to include the new placed images. - msi_bmp = sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) - col_msi_png = sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) - - msg = "The file has been created successfully inside the 'public' folder of the app." - #println("all msi in folder = ",msi_bmp) + msi_bmp=sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + col_msi_png=sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) + selectedTab="tab0" + msg="The file has been created successfully inside the 'public' folder of the app." + #println("all msi in folder=",msi_bmp) #println("all col msi in folder= ",col_msi_png) end catch e - msg = "There was an error loading the ImzML file, please verify the file accordingly and try again. $(e)" - warning_msg = true + msg="There was an error loading the ImzML file, please verify the file accordingly and try again. $(e)" + warning_msg=true end else - msg = "File does not exist or a parameter is incorrect, please try again." - warning_msg = true + msg="File does not exist or a parameter is incorrect, please try again." + warning_msg=true end - spectra = nothing # Important for memory cleaning - slice = nothing + spectra=nothing # Important for memory cleaning + slice=nothing GC.gc() # Trigger garbage collection if Sys.islinux() ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure julia returns the freed memory to OS end - btnStartDisable = false - progress = false + btnStartDisable=false + btnPlotDisable=false + progress=false end @onbutton createSumPlot begin - msg = "Sum spectrum plot selected" - full_route = joinpath( file_route, file_name ) + msg="Sum spectrum plot selected" + #full_route=joinpath( file_route, file_name ) if isfile(full_route) # Check if the file exists - btnPlotDisable = false - btnStartDisable = false - full_routeMz = split( full_route, "." )[1] * ".mzML" # Splitting the route from imzml to mzml so the plotting can work + btnPlotDisable=false + btnStartDisable=false + full_routeMz=split( full_route, "." )[1] * ".mzML" # Splitting the route from imzml to mzml so the plotting can work if isfile(full_routeMz) && (full_routeMz2 == "" || full_routeMz2 != full_routeMz) # Check if the mzml exists println("I'm working as intended") - progressPlot = true - btnPlotDisable = true - btnStartDisable = true - msg = "Loading plot..." - spectraMz = LoadMzml(full_routeMz) - layoutSpectra = PlotlyBase.Layout( - title = "SUM Spectrum plot", - xaxis = PlotlyBase.attr( - title = "m/z", - showgrid = true + progressPlot=true + btnPlotDisable=true + btnStartDisable=true + msg="Loading plot..." + spectraMz=LoadMzml(full_routeMz) + layoutSpectra=PlotlyBase.Layout( + title="SUM Spectrum plot", + xaxis=PlotlyBase.attr( + title="m/z", + showgrid=true + ), - yaxis = PlotlyBase.attr( - title = "Intensity", - showgrid = true + yaxis=PlotlyBase.attr( + title="Intensity", + showgrid=true ) ) - # dims = size(spectraMz) - # scansMax = dims[2] # we get the total of scansMax - # traceSpectra = PlotlyBase.scatter(x = spectraMz[1, 1], y = spectraMz[2, 1], mode="lines") - traceSpectra = PlotlyBase.scatter(x = mean(spectraMz[1,:]), y = mean(spectraMz[2,:]), mode="lines") - plotdata = [traceSpectra] # We add the data from spectra to the plot - plotlayout = layoutSpectra - spectraMz = nothing # Important for memory cleaning + # dims=size(spectraMz) + # scansMax=dims[2] # we get the total of scansMax + # traceSpectra=PlotlyBase.scatter(x=spectraMz[1, 1], y=spectraMz[2, 1], mode="lines") + traceSpectra=PlotlyBase.scatter(x=mean(spectraMz[1,:]), y=mean(spectraMz[2,:]), mode="lines") + plotdata=[traceSpectra] # We add the data from spectra to the plot + plotlayout=layoutSpectra + spectraMz=nothing # Important for memory cleaning GC.gc() # Trigger garbage collection if Sys.islinux() ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure julia returns the freed memory to OS end - msg = "Plot loaded." - full_routeMz2 = full_routeMz # To avoid creating the plot if its the same file read as before + selectedTab="tab2" + msg="Plot loaded." + full_routeMz2=full_routeMz # To avoid creating the plot if its the same file read as before + else + msg="the mzML file was not found" + warning_msg=true end else - msg = "is not an imzML file" - warning_msg = true + msg="is not an imzML file" + warning_msg=true end - progressPlot = false - btnPlotDisable = false - btnStartDisable = false + progressPlot=false + btnPlotDisable=false + btnStartDisable=false end # Image loaders based on the position of the current image (increment and decrement for both normal and filter) # And a pre-generated list from all image files from /public folder @onbutton ImgMinus begin # Append a query string to force the image to refresh - timestamp = string(time_ns()) + timestamp=string(time_ns()) # Update the array of images listed in the public folder - msi_bmp = sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) - col_msi_png = sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) + msi_bmp=sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + col_msi_png=sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) - new_msi = decrement_image(current_msi, msi_bmp) - new_col_msi = decrement_image(current_col_msi, col_msi_png) + new_msi=decrement_image(current_msi, msi_bmp) + new_col_msi=decrement_image(current_col_msi, col_msi_png) - current_msi = new_msi - current_col_msi = new_col_msi - imgInt = "/$(current_msi)?t=$(timestamp)" - colorbar = "/$(current_col_msi)?t=$(timestamp)" + current_msi=new_msi + current_col_msi=new_col_msi + imgInt="/$(current_msi)?t=$(timestamp)" + colorbar="/$(current_col_msi)?t=$(timestamp)" - text_nmass = replace(current_msi, "MSI_" => "") - text_nmass = replace(text_nmass, ".bmp" => "") - msgimg = "image with the Nmass of $(replace(text_nmass, "_" => "."))" + text_nmass=replace(current_msi, "MSI_" => "") + text_nmass=replace(text_nmass, ".bmp" => "") + msgimg="Image with the Nmass of $(replace(text_nmass, "_" => "."))" end @onbutton ImgPlus begin # Append a query string to force the image to refresh - timestamp = string(time_ns()) + timestamp=string(time_ns()) # Update the array of images listed in the public folder - msi_bmp = sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) - col_msi_png = sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) + msi_bmp=sort(filter(filename -> startswith(filename, "MSI_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + col_msi_png=sort(filter(filename -> startswith(filename, "colorbar_MSI_") && endswith(filename, ".png"), readdir("public")),lt=natural) - new_msi = increment_image(current_msi, msi_bmp) - new_col_msi = increment_image(current_col_msi, col_msi_png) + new_msi=increment_image(current_msi, msi_bmp) + new_col_msi=increment_image(current_col_msi, col_msi_png) - current_msi = new_msi - current_col_msi = new_col_msi - imgInt = "/$(current_msi)?t=$(timestamp)" - colorbar = "/$(current_col_msi)?t=$(timestamp)" + current_msi=new_msi + current_col_msi=new_col_msi + imgInt="/$(current_msi)?t=$(timestamp)" + colorbar="/$(current_col_msi)?t=$(timestamp)" - text_nmass = replace(current_msi, "MSI_" => "") - text_nmass = replace(text_nmass, ".bmp" => "") - msgimg = "image with the Nmass of $(replace(text_nmass, "_" => "."))" + text_nmass=replace(current_msi, "MSI_" => "") + text_nmass=replace(text_nmass, ".bmp" => "") + msgimg="Image with the Nmass of $(replace(text_nmass, "_" => "."))" end @onbutton ImgMinusT begin # Append a query string to force the image to refresh - timestamp = string(time_ns()) - new_msi = decrement_image(current_triq, triq_bmp) - new_col_msi = decrement_image(current_col_triq, col_triq_png) + timestamp=string(time_ns()) + new_msi=decrement_image(current_triq, triq_bmp) + new_col_msi=decrement_image(current_col_triq, col_triq_png) # Update the array of images with TrIQ filter listed in the public folder - triq_bmp = sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) - col_triq_png = sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) + triq_bmp=sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + col_triq_png=sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) - current_triq = new_msi - current_col_triq = new_col_msi - imgIntT = "/$(current_triq)?t=$(timestamp)" - colorbarT = "/$(current_col_triq)?t=$(timestamp)" + current_triq=new_msi + current_col_triq=new_col_msi + imgIntT="/$(current_triq)?t=$(timestamp)" + colorbarT="/$(current_col_triq)?t=$(timestamp)" - text_nmass = replace(current_triq, "TrIQ_" => "") - text_nmass = replace(text_nmass, ".bmp" => "") - msgtriq = "image with the Nmass of $(replace(text_nmass, "_" => "."))" + text_nmass=replace(current_triq, "TrIQ_" => "") + text_nmass=replace(text_nmass, ".bmp" => "") + msgtriq="TrIQ image with the Nmass of $(replace(text_nmass, "_" => "."))" end @onbutton ImgPlusT begin # Append a query string to force the image to refresh - timestamp = string(time_ns()) - new_msi = increment_image(current_triq, triq_bmp) - new_col_msi = increment_image(current_col_triq, col_triq_png) + timestamp=string(time_ns()) + new_msi=increment_image(current_triq, triq_bmp) + new_col_msi=increment_image(current_col_triq, col_triq_png) # Update the array of images with TrIQ filter listed in the public folder - triq_bmp = sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) - col_triq_png = sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) + triq_bmp=sort(filter(filename -> startswith(filename, "TrIQ_") && endswith(filename, ".bmp"), readdir("public")),lt=natural) + col_triq_png=sort(filter(filename -> startswith(filename, "colorbar_TrIQ_") && endswith(filename, ".png"), readdir("public")),lt=natural) - current_triq = new_msi - current_col_triq = new_col_msi - imgIntT = "/$(current_triq)" - colorbarT = "/$(current_col_triq)" + current_triq=new_msi + current_col_triq=new_col_msi + imgIntT="/$(current_triq)" + colorbarT="/$(current_col_triq)" - text_nmass = replace(current_triq, "TrIQ_" => "") - text_nmass = replace(text_nmass, ".bmp" => "") - msgtriq = "image with the Nmass of $(replace(text_nmass, "_" => "."))" + text_nmass=replace(current_triq, "TrIQ_" => "") + text_nmass=replace(text_nmass, ".bmp" => "") + msgtriq="TrIQ image with the Nmass of $(replace(text_nmass, "_" => "."))" end # 3d plot @onbutton image3dPlot begin - msg = "Image 3D plot selected" - cleaned_imgInt = replace(imgInt, r"\?.*" => "") - cleaned_imgInt = lstrip(cleaned_imgInt, '/') - var = joinpath( "./public", cleaned_imgInt ) + msg="Image 3D plot selected" + cleaned_imgInt=replace(imgInt, r"\?.*" => "") + cleaned_imgInt=lstrip(cleaned_imgInt, '/') + var=joinpath( "./public", cleaned_imgInt ) if isfile(var) - progressPlot = true - btnPlotDisable = true - btnStartDisable = true + progressPlot=true + btnPlotDisable=true + btnStartDisable=true try - img = load(var) + img=load(var) #println("Image type:", typeof(img)) - img_gray = Gray.(img) # Convert to grayscale + img_gray=Gray.(img) # Convert to grayscale #println("Grayscale image type:", typeof(img_gray)) - img_array = Array(img_gray) - elevation = Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 + img_array=Array(img_gray) + elevation=Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 #println("Elevation size:", size(elevation)) # Smooth the image - sigma = 3.0 - kernel = Kernel.gaussian(sigma) + sigma=3.0 + kernel=Kernel.gaussian(sigma) #println(size(kernel)) - elevation_smoothed = imfilter(elevation, kernel) + elevation_smoothed=imfilter(elevation, kernel) #println("Smoothed elevation size:", size(elevation_smoothed)) # Transpose the elevation_smoothed array # Create the X, Y meshgrid coordinates - x = 1:size(elevation_smoothed, 2) - y = 1:size(elevation_smoothed, 1) - X = repeat(reshape(x, 1, length(x)), length(y), 1) + x=1:size(elevation_smoothed, 2) + y=1:size(elevation_smoothed, 1) + X=repeat(reshape(x, 1, length(x)), length(y), 1) #println("Size of X:", size(X)) - Y = repeat(reshape(y, length(y), 1), 1, length(x)) + Y=repeat(reshape(y, length(y), 1), 1, length(x)) #println("Size of Y:", size(Y)) # Calculate the number of ticks and aspect ratio for the 3d plot - x_nticks = min(20, length(x)) - y_nticks = min(20, length(y)) - z_nticks = 5 - aspect_ratio = attr(x = 1, y = length(y) / length(x), z = 0.5) + x_nticks=min(20, length(x)) + y_nticks=min(20, length(y)) + z_nticks=5 + aspect_ratio=attr(x=1, y=length(y) / length(x), z=0.5) # Define the layout for the 3D plot - layout3D = PlotlyBase.Layout( - title = "3D Surface Plot", - scene = attr( - xaxis_nticks = x_nticks, - yaxis_nticks = y_nticks, - zaxis_nticks = z_nticks, - camera = attr(eye = attr(x = 0, y = -1, z = 0.5)), - aspectratio = aspect_ratio + layout3D=PlotlyBase.Layout( + title="3D Surface Plot", + scene=attr( + xaxis_nticks=x_nticks, + yaxis_nticks=y_nticks, + zaxis_nticks=z_nticks, + camera=attr(eye=attr(x=0, y=-1, z=0.5)), + aspectratio=aspect_ratio ) ) if size(elevation_smoothed, 1) < size(elevation_smoothed, 2) # Transpose the elevation_smoothed array if Y axis is longer than X axis to fix chopping - elevation_smoothed = transpose(elevation_smoothed) - Y = -Y + elevation_smoothed=transpose(elevation_smoothed) + Y=-Y end - trace3D = PlotlyBase.surface(x = X[1, :], y = Y[:, 1], z = elevation_smoothed, - contours_z = attr( - show = true, - usecolormap = true, - highlightcolor = "limegreen", - project_z = true - ), colorscale = "Viridis") - plotdata3d = [trace3D] # We add the data from the image to the plot - plotlayout3d = layout3D # we update the style of the plot to fit the image. - spectraMz = nothing # Important for memory cleaning + trace3D=PlotlyBase.surface(x=X[1, :], y=Y[:, 1], z=elevation_smoothed, + contours_z=attr( + show=true, + usecolormap=true, + highlightcolor="limegreen", + project_z=true + ), colorscale="Viridis") + plotdata3d=[trace3D] # We add the data from the image to the plot + plotlayout3d=layout3D # we update the style of the plot to fit the image. + spectraMz=nothing # Important for memory cleaning GC.gc() # Trigger garbage collection if Sys.islinux() ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure julia returns the freed memory to OS end - msg = "Plot loaded." + selectedTab="tab4" + msg="Plot loaded." catch e - msg = "Failed to load and process image: $e" - warning_msg = true + msg="Failed to load and process image: $e" + warning_msg=true println(msg) end else - msg = "image could not be 3d plotted" - warning_msg = true + msg="Image could not be 3d plotted" + warning_msg=true end - progressPlot = false - btnPlotDisable = false - btnStartDisable = false + progressPlot=false + btnPlotDisable=false + btnStartDisable=false end # 3d plot for TrIQ @onbutton triq3dPlot begin - msg = "TrIQ 3D plot selected" - cleaned_imgIntT = replace(imgIntT, r"\?.*" => "") - cleaned_imgIntT = lstrip(cleaned_imgIntT, '/') - var = joinpath( "./public", cleaned_imgIntT ) + msg="TrIQ 3D plot selected" + cleaned_imgIntT=replace(imgIntT, r"\?.*" => "") + cleaned_imgIntT=lstrip(cleaned_imgIntT, '/') + var=joinpath( "./public", cleaned_imgIntT ) if isfile(var) - progressPlot = true - btnPlotDisable = true - btnStartDisable = true + progressPlot=true + btnPlotDisable=true + btnStartDisable=true try - img = load(var) - img_gray = Gray.(img) # Convert to grayscale - img_array = Array(img_gray) - elevation = Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 + img=load(var) + img_gray=Gray.(img) # Convert to grayscale + img_array=Array(img_gray) + elevation=Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 # Smooth the image - sigma = 3.0 - kernel = Kernel.gaussian(sigma) - elevation_smoothed = imfilter(elevation, kernel) + sigma=3.0 + kernel=Kernel.gaussian(sigma) + elevation_smoothed=imfilter(elevation, kernel) # Create the X, Y meshgrid coordinates - x = 1:size(elevation_smoothed, 2) - y = 1:size(elevation_smoothed, 1) - X = repeat(reshape(x, 1, length(x)), length(y), 1) - Y = repeat(reshape(y, length(y), 1), 1, length(x)) + x=1:size(elevation_smoothed, 2) + y=1:size(elevation_smoothed, 1) + X=repeat(reshape(x, 1, length(x)), length(y), 1) + Y=repeat(reshape(y, length(y), 1), 1, length(x)) # Calculate the number of ticks and aspect ratio for the 3d plot - x_nticks = min(20, length(x)) - y_nticks = min(20, length(y)) - z_nticks = 5 - aspect_ratio = attr(x = 1, y = length(y) / length(x), z = 0.5) + x_nticks=min(20, length(x)) + y_nticks=min(20, length(y)) + z_nticks=5 + aspect_ratio=attr(x=1, y=length(y) / length(x), z=0.5) # Define the layout for the 3D plot - layout3D = PlotlyBase.Layout( - title = "3D Surface Plot", - scene = attr( - xaxis_nticks = x_nticks, - yaxis_nticks = y_nticks, - zaxis_nticks = z_nticks, - camera = attr(eye = attr(x = 0, y = -1, z = 0.5)), - aspectratio = aspect_ratio + layout3D=PlotlyBase.Layout( + title="3D Surface Plot", + scene=attr( + xaxis_nticks=x_nticks, + yaxis_nticks=y_nticks, + zaxis_nticks=z_nticks, + camera=attr(eye=attr(x=0, y=-1, z=0.5)), + aspectratio=aspect_ratio ) ) if size(elevation_smoothed, 1) < size(elevation_smoothed, 2) # Transpose the elevation_smoothed array if Y axis is longer than X axis to fix chopping - elevation_smoothed = transpose(elevation_smoothed) - Y = -Y + elevation_smoothed=transpose(elevation_smoothed) + Y=-Y end - trace3D = PlotlyBase.surface(x = X[1, :], y = Y[:, 1], z = elevation_smoothed, - contours_z = attr( - show = true, - usecolormap = true, - highlightcolor = "limegreen", - project_z = true - ), colorscale = "Viridis") - plotdata3d = [trace3D] # We add the data from the image to the plot - plotlayout3d = layout3D # we update the style of the plot to fit the image. - spectraMz = nothing # Important for memory cleaning + trace3D=PlotlyBase.surface(x=X[1, :], y=Y[:, 1], z=elevation_smoothed, + contours_z=attr( + show=true, + usecolormap=true, + highlightcolor="limegreen", + project_z=true + ), colorscale="Viridis") + plotdata3d=[trace3D] # We add the data from the image to the plot + plotlayout3d=layout3D # we update the style of the plot to fit the image. + spectraMz=nothing # Important for memory cleaning GC.gc() # Trigger garbage collection if Sys.islinux() ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure julia returns the freed memory to OS end - msg = "Plot loaded." + selectedTab="tab4" + msg="Plot loaded." catch e - msg = "Failed to load and process image: $e" - warning_msg = true + msg="Failed to load and process image: $e" + warning_msg=true println(msg) end else - msg = "image could not be 3d plotted" - warning_msg = true + msg="Image could not be 3d plotted" + warning_msg=true end - progressPlot = false - btnPlotDisable = false - btnStartDisable = false + progressPlot=false + btnPlotDisable=false + btnStartDisable=false end # Contour 2d plot @onbutton imageCPlot begin - msg = "Image 2D plot selected" - cleaned_imgInt = replace(imgInt, r"\?.*" => "") - cleaned_imgInt = lstrip(cleaned_imgInt, '/') - var = joinpath("./public", cleaned_imgInt) + msg="Image 2D plot selected" + cleaned_imgInt=replace(imgInt, r"\?.*" => "") + cleaned_imgInt=lstrip(cleaned_imgInt, '/') + var=joinpath("./public", cleaned_imgInt) if isfile(var) - progressPlot = true - btnPlotDisable = true - btnStartDisable = true + progressPlot=true + btnPlotDisable=true + btnStartDisable=true try - img = load(var) + img=load(var) # Convert to grayscale - img_gray = Gray.(img) - img_array = Array(img_gray) - elevation = Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 + img_gray=Gray.(img) + img_array=Array(img_gray) + elevation=Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 # Smooth the image - sigma = 3.0 - kernel = Kernel.gaussian(sigma) - elevation_smoothed = imfilter(elevation, kernel) + sigma=3.0 + kernel=Kernel.gaussian(sigma) + elevation_smoothed=imfilter(elevation, kernel) # Create the X, Y meshgrid coordinates - x = 1:size(elevation_smoothed, 2) - y = 1:size(elevation_smoothed, 1) - X = repeat(reshape(x, 1, length(x)), length(y), 1) - Y = repeat(reshape(y, length(y), 1), 1, length(x)) + x=1:size(elevation_smoothed, 2) + y=1:size(elevation_smoothed, 1) + X=repeat(reshape(x, 1, length(x)), length(y), 1) + Y=repeat(reshape(y, length(y), 1), 1, length(x)) - layoutContour = PlotlyBase.Layout( - title = "2D Topographic Map", - xaxis_title = "X", - yaxis_title = "Y", - margin = attr(l = 65, r = 50, b = 65, t = 90) + layoutContour=PlotlyBase.Layout( + title="2D Topographic Map", + xaxis_title="X", + yaxis_title="Y" + ) - traceContour = PlotlyBase.contour( - z = elevation_smoothed, - x = X[1, :], # Use the first row - y = -Y[:, 1], # Use the first column - contours_coloring = "Viridis", - colorscale = "Viridis" + traceContour=PlotlyBase.contour( + z=elevation_smoothed, + x=X[1, :], # Use the first row + y=-Y[:, 1], # Use the first column + contours_coloring="Viridis", + colorscale="Viridis" ) - plotdata = [traceContour] - plotlayout = layoutContour + plotdataC=[traceContour] + plotlayoutC=layoutContour - spectraMz = nothing # Important for memory cleaning + spectraMz=nothing # Important for memory cleaning GC.gc() # Trigger garbage collection if Sys.islinux() ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure Julia returns the freed memory to OS end - msg = "Plot loaded." + selectedTab="tab3" + msg="Plot loaded." catch e - msg = "Failed to load and process image: $e" - warning_msg = true + msg="Failed to load and process image: $e" + warning_msg=true println(msg) end else - msg = "Image could not be 2D plotted" - warning_msg = true + msg="Image could not be 2D plotted" + warning_msg=true end - progressPlot = false - btnPlotDisable = false - btnStartDisable = false + progressPlot=false + btnPlotDisable=false + btnStartDisable=false end # Contour 2d plot for TrIQ @onbutton triqCPlot begin - msg = "Image 2D plot selected" - cleaned_imgIntT = replace(imgIntT, r"\?.*" => "") - cleaned_imgIntT = lstrip(cleaned_imgIntT, '/') - var = joinpath("./public", cleaned_imgIntT) + msg="Image 2D plot selected" + cleaned_imgIntT=replace(imgIntT, r"\?.*" => "") + cleaned_imgIntT=lstrip(cleaned_imgIntT, '/') + var=joinpath("./public", cleaned_imgIntT) if isfile(var) - progressPlot = true - btnPlotDisable = true - btnStartDisable = true + progressPlot=true + btnPlotDisable=true + btnStartDisable=true try - img = load(var) + img=load(var) # Convert to grayscale - img_gray = Gray.(img) - img_array = Array(img_gray) - elevation = Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 + img_gray=Gray.(img) + img_array=Array(img_gray) + elevation=Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 # Smooth the image - sigma = 3.0 - kernel = Kernel.gaussian(sigma) - elevation_smoothed = imfilter(elevation, kernel) + sigma=3.0 + kernel=Kernel.gaussian(sigma) + elevation_smoothed=imfilter(elevation, kernel) # Create the X, Y meshgrid coordinates - x = 1:size(elevation_smoothed, 2) - y = 1:size(elevation_smoothed, 1) - X = repeat(reshape(x, 1, length(x)), length(y), 1) - Y = repeat(reshape(y, length(y), 1), 1, length(x)) + x=1:size(elevation_smoothed, 2) + y=1:size(elevation_smoothed, 1) + X=repeat(reshape(x, 1, length(x)), length(y), 1) + Y=repeat(reshape(y, length(y), 1), 1, length(x)) - layoutContour = PlotlyBase.Layout( - title = "2D Topographic Map", - xaxis_title = "X", - yaxis_title = "Y", - margin = attr(l = 65, r = 50, b = 65, t = 90) + layoutContour=PlotlyBase.Layout( + title="2D Topographic Map", + xaxis_title="X", + yaxis_title="Y", + ) - traceContour = PlotlyBase.contour( - z = elevation_smoothed, - x = X[1, :], # Use the first row - y = -Y[:, 1], # Use the first column - contours_coloring = "Viridis", - colorscale = "Viridis" + traceContour=PlotlyBase.contour( + z=elevation_smoothed, + x=X[1, :], # Use the first row + y=-Y[:, 1], # Use the first column + contours_coloring="Viridis", + colorscale="Viridis" ) - plotdata = [traceContour] - plotlayout = layoutContour + plotdataC=[traceContour] + plotlayoutC=layoutContour - spectraMz = nothing # Important for memory cleaning + spectraMz=nothing # Important for memory cleaning GC.gc() # Trigger garbage collection if Sys.islinux() ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure Julia returns the freed memory to OS end - msg = "Plot loaded." + selectedTab="tab3" + msg="Plot loaded." catch e - msg = "Failed to load and process image: $e" - warning_msg = true + msg="Failed to load and process image: $e" + warning_msg=true println(msg) end else - msg = "Image could not be 2D plotted" - warning_msg = true + msg="Image could not be 2D plotted" + warning_msg=true end - progressPlot = false - btnPlotDisable = false - btnStartDisable = false + progressPlot=false + btnPlotDisable=false + btnStartDisable=false end @onbutton CompareBtn begin - CompareDialog = true + CompareDialog=true end GC.gc() # Trigger garbage collection @@ -747,7 +775,7 @@ end - The @private macro defines a reactive variable that is not sent to the browser. This is useful for storing data that is unique to each user session but is not needed in the UI. - @private table = DataFrame(a = 1:10, b = 10:19, c = 20:29) + @private table=DataFrame(a=1:10, b=10:19, c=20:29) =# diff --git a/app.jl.html b/app.jl.html index 86add60..ae07792 100644 --- a/app.jl.html +++ b/app.jl.html @@ -9,16 +9,19 @@
-
+
- + +
Search for your imzML file in your device
+ +
- + - + Sum Spectrum Plot - + Image Contour Plot - + TrIQ Contour Plot - + Image 3D Plot - + TrIQ 3D Plot @@ -91,32 +94,29 @@
- - Start Process + - - Compare - +

{{msg}}

-
+
- +
Image Visualizer
- - + +
@@ -135,8 +135,8 @@
TrIQ Visualizer
- - + +
@@ -151,11 +151,15 @@ - + - - + + + + + +
@@ -187,14 +191,14 @@
- +
- - + +
@@ -212,8 +216,8 @@
- - + +
@@ -228,23 +232,27 @@ - + - - + + + + + +
- - + +
- - + +
@@ -262,8 +270,8 @@
- - + +
@@ -278,11 +286,15 @@ - + - - + + + + + +
diff --git a/public/css/autogenerated.css b/public/css/autogenerated.css index 1c4c15e..77daecf 100644 --- a/public/css/autogenerated.css +++ b/public/css/autogenerated.css @@ -1 +1 @@ -#btnStyle{background:#009f90;color:rgb(229, 236, 246);}#imgInt{float:left;}#header{display:flex;align-items:center;}#imgLogo{width:100px;height:80px;margin-right:10px;margin-left:10px;}#extDivStyle{background-color:#c9cdb1;border-radius: 10px;}#intDivStyle{padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;background-color: #eff2f5;}#colorbar{float:left;}.custom-standout{background-color:#7f8389!important;color:rgb(0, 0, 0)!important;} \ No newline at end of file +#btnStyle{background:#009f90;color:rgb(229, 236, 246);}#imgInt{float:left;}#header{display:flex;align-items:center;}#imgLogo{width:100px;height:80px;margin-right:10px;margin-left:10px;}#extDivStyle{background-color:#c9cdb1;border-radius: 10px;}#intDivStyle{padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;background-color: #eff2f5;}#colorbar{float:left;}.custom-standout{background-color:#7f8389!important;color:rgb(0, 0, 0)!important;}#tabHeader{color:#009f90;} \ No newline at end of file diff --git a/start_MSI_GUI.jl b/start_MSI_GUI.jl index 6d6ea81..72bec77 100644 --- a/start_MSI_GUI.jl +++ b/start_MSI_GUI.jl @@ -6,6 +6,7 @@ Pkg.gc() Pkg.add("Libz") ; Pkg.add("PlotlyBase") ; Pkg.add("CairoMakie") ; Pkg.add("Colors") ; Pkg.add("Statistics") ; Pkg.add("NaturalSort") ; Pkg.add("GenieFramework") ;Pkg.add("Genie") Pkg.add(url="https://github.com/CINVESTAV-LABI/julia_mzML_imzML") # With this we ensure it uses the latest library iteration Pkg.add("Images") ; Pkg.add("LinearAlgebra") +Pkg.add("NativeFileDialog") using Genie