Added plot interaction to the UI, improved boot loading, modified UI to accomodate for these changes

This commit is contained in:
Pixelguy14 2025-01-22 23:58:06 -06:00
parent bf50d0cb0c
commit 09e4a015e0
6 changed files with 641 additions and 445 deletions

View File

@ -242,9 +242,9 @@ version = "0.4.1"
[[deps.ColorSchemes]]
deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"]
git-tree-sha1 = "c785dfb1b3bfddd1da557e861b919819b82bbe5b"
git-tree-sha1 = "26ec26c98ae1453c692efded2b17e15125a5bea1"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.27.1"
version = "3.28.0"
[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
@ -525,9 +525,9 @@ version = "0.3.2"
[[deps.FFTW]]
deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"]
git-tree-sha1 = "4820348781ae578893311153d69049a93d05f39d"
git-tree-sha1 = "7de7c78d681078f027389e067864a8d53bd7c3c9"
uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
version = "1.8.0"
version = "1.8.1"
[[deps.FFTW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
@ -708,15 +708,15 @@ uuid = "5c4fdc26-39e3-47cf-9034-e533e09961c2"
version = "1.1.0"
[[deps.GeoFormatTypes]]
git-tree-sha1 = "ce573eab15760315756de2c82df7406c870c7187"
git-tree-sha1 = "8e233d5167e63d708d41f87597433f59a0f213fe"
uuid = "68eda718-8dee-11e9-39e7-89f7f65f511f"
version = "0.4.3"
version = "0.4.4"
[[deps.GeoInterface]]
deps = ["DataAPI", "Extents", "GeoFormatTypes"]
git-tree-sha1 = "f4ee66b6b1872a4ca53303fbb51d158af1bf88d4"
git-tree-sha1 = "294e99f19869d0b0cb71aef92f19d03649d028d5"
uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f"
version = "1.4.0"
version = "1.4.1"
[[deps.GeometryBasics]]
deps = ["EarCut_jll", "Extents", "GeoInterface", "IterTools", "LinearAlgebra", "PrecompileTools", "Random", "StaticArrays"]
@ -814,9 +814,9 @@ version = "0.5.0"
[[deps.HypergeometricFunctions]]
deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"]
git-tree-sha1 = "b1c2585431c382e3fe5805874bda6aea90a95de9"
git-tree-sha1 = "2bd56245074fab4015b9174f24ceba8293209053"
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
version = "0.3.25"
version = "0.3.27"
[[deps.HypertextLiteral]]
deps = ["Tricks"]
@ -933,9 +933,9 @@ version = "0.10.1"
[[deps.Images]]
deps = ["Base64", "FileIO", "Graphics", "ImageAxes", "ImageBase", "ImageBinarization", "ImageContrastAdjustment", "ImageCore", "ImageCorners", "ImageDistances", "ImageFiltering", "ImageIO", "ImageMagick", "ImageMetadata", "ImageMorphology", "ImageQualityIndexes", "ImageSegmentation", "ImageShow", "ImageTransformations", "IndirectArrays", "IntegralArrays", "Random", "Reexport", "SparseArrays", "StaticArrays", "Statistics", "StatsBase", "TiledIteration"]
git-tree-sha1 = "12fdd617c7fe25dc4a6cc804d657cc4b2230302b"
git-tree-sha1 = "a49b96fd4a8d1a9a718dfd9cde34c154fc84fcd5"
uuid = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
version = "0.26.1"
version = "0.26.2"
[[deps.Imath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl"]
@ -980,9 +980,9 @@ version = "0.1.6"
[[deps.IntelOpenMP_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl"]
git-tree-sha1 = "10bd689145d2c3b2a9844005d01087cc1194e79e"
git-tree-sha1 = "0f14a5456bdc6b9731a5682f439a672750a09e48"
uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0"
version = "2024.2.1+0"
version = "2025.0.4+0"
[[deps.InteractiveUtils]]
deps = ["Markdown"]
@ -1350,9 +1350,9 @@ version = "0.1.4"
[[deps.MKL_jll]]
deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "oneTBB_jll"]
git-tree-sha1 = "f046ccd0c6db2832a9f639e2c669c6fe867e5f4f"
git-tree-sha1 = "5de60bc6cb3899cd318d80d627560fae2e2d99ae"
uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7"
version = "2024.2.0+0"
version = "2025.0.1+1"
[[deps.MacroTools]]
git-tree-sha1 = "72aebe0b5051e5143a079a4685a46da330a40472"
@ -1459,9 +1459,9 @@ version = "1.2.1"
[[deps.NaNMath]]
deps = ["OpenLibm_jll"]
git-tree-sha1 = "030ea22804ef91648f29b7ad3fc15fa49d0e6e71"
git-tree-sha1 = "fe891aea7ccd23897520db7f16931212454e277e"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "1.0.3"
version = "1.1.1"
[[deps.NativeFileDialog]]
deps = ["FilePathsBase", "NativeFileDialog_jll"]
@ -1921,9 +1921,9 @@ version = "1.3.0"
[[deps.Revise]]
deps = ["CodeTracking", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "REPL", "Requires", "UUIDs", "Unicode"]
git-tree-sha1 = "b5e7c125687aa818de948ef8a0b9dc59f043342c"
git-tree-sha1 = "9bb80533cb9769933954ea4ffbecb3025a783198"
uuid = "295af30f-e4ad-537b-8983-00126c2a3abe"
version = "3.7.1"
version = "3.7.2"
weakdeps = ["Distributed"]
[deps.Revise.extensions]

View File

@ -9,20 +9,16 @@ A Graphical User Interface for IMS in Julia: https://github.com/CINVESTAV-LABI/j
unzip the file in your desired location<br>
## Load User Interface
1. Launch Julia in your terminal using:
1. Set working directory to Julia_msi_GUI (this repository) in your terminal using:
```
julia
cd PathToRepository/Julia_msi_GUI-main
```
2. Set working directory to Julia_msi_GUI (this repository) code using:
2. Launch the Julia project in your terminal using:
```
cd("PathToRepository/Julia_msi_GUI-main")
julia --project=. start_MSI_GUI.jl
```
3. With the active directory being Julia_msi_GUI run the next script:
3. Alternatively, you can open a terminal in the path of the repository and run the command and skip the next step:
```
include("start_MSI_GUI.jl")
julia --project=. start_MSI_GUI.jl
```
4. Alternatively, you can open a terminal in the path of the repository and run the command and skip the next step:
```
julia start_MSI_GUI.jl
```
5. After the script has finished loading, it should open a page in your browser with the web app running.
4. After the script has finished loading, it should open a page (http://127.0.0.1:1481/) in your browser with the web app running.

344
app.jl
View File

@ -1,5 +1,5 @@
module App
# == Packages ==
# ==Packages ==
using GenieFramework # Set up Genie development environment.
using Pkg
using Libz
@ -15,18 +15,18 @@ using NativeFileDialog # Opens the file explorer depending on the OS
using StipplePlotly
@genietools
# == Code import ==
# ==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)
# == Search functions ==
# ==Search functions ==
function increment_image(current_image, image_list)
if isempty(image_list)
return nothing
end
current_index=findfirst(isequal(current_image), image_list)
if current_index == nothing || current_index == length(image_list) || current_image === ""
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
return image_list[current_index + 1] # Move to the next image
@ -38,31 +38,39 @@ function decrement_image(current_image, image_list)
return nothing
end
current_index=findfirst(isequal(current_image), image_list)
if current_index == nothing || current_index == 1 || current_image === ""
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
return image_list[current_index - 1] # Move to the previous image
end
end
# == Reactive code ==
# ==Reactive code ==
# reactive code to make the UI interactive
@app begin
# == Reactive variables ==
# ==Reactive variables ==
# reactive variables exist in both the Julia backend and the browser with two-way synchronization
# @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
# Interface non Variables
@out warning_fr=""
## Interface non Variables
@out btnStartDisable=true
@out btnPlotDisable=false
@out btnSpectraDisable=true
# Loading animations
@in progress=false
@in progressPlot=false
@in progressSpectraPlot=false
# Text field validations
@in triqEnabled=false
@in SpectraEnabled=false
# Dialogs
@in warning_msg=false
@in CompareDialog=false
# Interface Variables
## Interface Variables
@in file_route=""
@in file_name=""
@in Nmass=0.0
@ -70,38 +78,39 @@ end
@in triqProb=0.98
@in triqColor=256
# Interface Buttons and Validations
## Interface Buttons
@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 createXYPlot=false # To generate an spectrum plot according to the xy values inputed
@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
# Image change buttons
@in imgPlus=false
@in imgMinus=false
@in imgPlusT=false
@in imgMinusT=false
# TAB variables
## Tabulation variables
@out tabIDs=["tab0","tab1","tab2","tab3","tab4"]
@out tabLabels=["Image", "TrIQ", "Spectrum Plot", "Topology Plot","Surface Plot"]
@in selectedTab= "tab0"
@in selectedTab="tab0"
@out CompTabIDs=["tab0","tab1","tab2","tab3","tab4"]
@out CompTabLabels=["Image", "TrIQ", "Spectrum Plot", "Topology Plot","Surface Plot"]
@in CompSelectedTab= "tab0"
@in CompSelectedTab="tab0"
# Interface Images
@out imgInt="/.bmp" # image Interface
@out imgIntT="/.bmp" # image Interface TrIQ
@out colorbar="/.png"
@out colorbarT="/.png"
@out img_width=0
@out img_height=0
# Messages to interface Variables
# Messages to interface variables
@out msg=""
@out msgimg=""
@out msgtriq=""
@ -126,11 +135,12 @@ end
@out current_triq=""
@out current_col_triq=""
# Starting and finishing times to measure how long it takes for a function to finish in elapse time
## Time measurement variables
@out sTime=time()
@out fTime=time()
@out eTime=time()
## Plots
# Interface Plot Spectrum
layoutSpectra=PlotlyBase.Layout(
title="SUM Spectrum plot",
@ -148,10 +158,14 @@ end
# Create conection to frontend
@out plotdata=[traceSpectra]
@out plotlayout=layoutSpectra
@in xCoord=0
@in yCoord=0
@out xSpectraMz=Float64[]
@out ySpectraMz=Float64[]
# Interactive plot reactions
@in data_click = Dict{String,Any}()
#@in data_selected = Dict{String,Any}() # Selected is for areas, this can work for the masks
@in data_click=Dict{String,Any}()
#@in data_selected=Dict{String,Any}() # Selected is for areas, this can work for the masks
#<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" @click="data_selected" class="q-pa-none q-ma-none sync_data"></plotly>
# Interface Plot Surface
@ -159,13 +173,12 @@ end
title="2D Topographic Map",
xaxis=PlotlyBase.attr(
title="X",
showgrid=true
),
yaxis=PlotlyBase.attr(
title="Y",
showgrid=true
scaleanchor="y"
),
yaxis=PlotlyBase.attr(
title="Y"
),
)
)
# Dummy 2D surface plot
traceContour=PlotlyBase.scatter(x=[], y=[], mode="lines")
# Create conection to frontend
@ -203,7 +216,7 @@ end
@out plotdata3d=[trace3D]
@out plotlayout3d=layout3D
# == Reactive handlers ==
# ==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
@ -218,10 +231,12 @@ end
#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)
full_routeMz=split( full_route, "." )[1] * ".mzML" # Splitting the route from imzml to mzml so the plotting can work
if isfile(full_routeMz)
# We enable coord search and spectra plot creation
btnSpectraDisable=false
SpectraEnabled=true
end
end
end
@ -229,10 +244,11 @@ end
progress=true # Start progress button animation
btnStartDisable=true # We disable the button to avoid multiple requests
btnPlotDisable=true
btnSpectraDisable=true
text_nmass=replace(string(Nmass), "." => "_")
sTime=time()
#full_route=joinpath(file_route, file_name)
if isfile(full_route) && Nmass > 0 && Tol > 0 && Tol <= 1
if isfile(full_route) && Nmass > 0 && Tol > 0 && Tol <=1
msg="File exists, Nmass=$(Nmass) Tol=$(Tol). Loading file will begin, please be patient."
try
spectra=LoadImzml(full_route)
@ -254,6 +270,8 @@ end
img=reverse(permutedims(img, (2, 1)), dims=1)
end
flipped_img=reverse(img, dims=1)
img_width=size(flipped_img, 2)
img_height=size(flipped_img, 1)
save(image_path, flipped_img)
# Use timestamp to refresh image interface container
imgIntT="/TrIQ_$(text_nmass).bmp?t=$(timestamp)"
@ -275,7 +293,7 @@ end
msg="The file has been created in $(eTime) seconds 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)
#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")
@ -286,6 +304,8 @@ end
img=reverse(permutedims(img, (2, 1)), dims=1)
end
flipped_img=reverse(img, dims=1)
img_width=size(flipped_img, 2)
img_height=size(flipped_img, 1)
save(image_path, flipped_img)
# Use timestamp to refresh image interface container
imgInt="/MSI_$(text_nmass).bmp?t=$(timestamp)"
@ -307,7 +327,7 @@ end
eTime=round(fTime-sTime,digits=3)
msg="The file has been created in $(eTime) seconds successfully inside the 'public' folder of the app"
#println("all msi in folder=",msi_bmp)
#println("all col msi in folder= ",col_msi_png)
#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)"
@ -325,6 +345,11 @@ end
end
btnStartDisable=false
btnPlotDisable=false
if isfile(full_routeMz)
# We enable coord search and spectra plot creation
btnSpectraDisable=false
SpectraEnabled=true
end
progress=false
end
@ -332,55 +357,101 @@ end
msg="Sum spectrum plot selected"
sTime=time()
#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
if isfile(full_routeMz) && (full_routeMz2 == "" || full_routeMz2 != full_routeMz) # Check if the mzml exists
progressPlot=true
btnPlotDisable=true
btnStartDisable=true
msg="Loading plot..."
spectraMz=LoadMzml(full_routeMz)
layoutSpectra=PlotlyBase.Layout(
title="SUM Spectrum plot",
xaxis=PlotlyBase.attr(
title="<i>m/z</i>",
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
GC.gc() # Trigger garbage collection
if Sys.islinux()
ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure julia returns the freed memory to OS
end
selectedTab="tab2"
fTime=time()
eTime=round(fTime-sTime,digits=3)
msg="Plot loaded in $(eTime) seconds"
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 or you're trying to load the same mzML"
warning_msg=true
if isfile(full_routeMz) # Check if the file exists
progressSpectraPlot=true
btnPlotDisable=true
btnStartDisable=true
msg="Loading plot..."
spectraMz=LoadMzml(full_routeMz)
layoutSpectra=PlotlyBase.Layout(
title="SUM Spectrum plot",
xaxis=PlotlyBase.attr(
title="<i>m/z</i>",
showgrid=true
),
yaxis=PlotlyBase.attr(
title="Intensity",
showgrid=true
),
autosize=false
)
# dims=size(spectraMz)
# scansMax=dims[2] # we get the total of scansMax
xSpectraMz=mean(spectraMz[1,:])
ySpectraMz=mean(spectraMz[2,:])
traceSpectra=PlotlyBase.scatter(x=xSpectraMz, y=ySpectraMz, mode="lines")
plotdata=[traceSpectra] # We add the data from spectra to the plot
plotlayout=layoutSpectra
GC.gc() # Trigger garbage collection
if Sys.islinux()
ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure julia returns the freed memory to OS
end
selectedTab="tab2"
fTime=time()
eTime=round(fTime-sTime,digits=3)
msg="Plot loaded in $(eTime) seconds"
else
msg="is not an imzML file"
msg="there was an error with the mzML, please try again"
warning_msg=true
end
progressPlot=false
progressSpectraPlot=false
btnPlotDisable=false
btnStartDisable=false
if isfile(full_routeMz)
# We enable coord search and spectra plot creation
btnSpectraDisable=false
SpectraEnabled=true
end
end
@onbutton createXYPlot begin
msg="Sum spectrum plot selected"
sTime=time()
#full_route=joinpath( file_route, file_name )
if isfile(full_routeMz) # Check if the file exists
progressSpectraPlot=true
btnStartDisable=true
btnPlotDisable=true
btnSpectraDisable=true
msg="Loading plot..."
spectraMz=LoadMzml(full_routeMz)
layoutSpectra=PlotlyBase.Layout(
title="($xCoord, $yCoord) Specific spectrum plot",
xaxis=PlotlyBase.attr(
title="<i>m/z</i>",
showgrid=true
),
yaxis=PlotlyBase.attr(
title="Intensity",
showgrid=true
),
autosize=false
)
xSpectraMz=spectraMz[1,abs(xCoord)]
ySpectraMz=spectraMz[2,abs(yCoord)]
traceSpectra=PlotlyBase.scatter(x=xSpectraMz, y=ySpectraMz, mode="lines")
plotdata=[traceSpectra] # We add the data from spectra to the plot
plotlayout=layoutSpectra
GC.gc() # Trigger garbage collection
if Sys.islinux()
ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure julia returns the freed memory to OS
end
selectedTab="tab2"
fTime=time()
eTime=round(fTime-sTime,digits=3)
msg="Plot loaded in $(eTime) seconds"
else
msg="there was an error with the mzML or the coordenates, please try again"
warning_msg=true
end
progressSpectraPlot=false
btnPlotDisable=false
btnStartDisable=false
if isfile(full_routeMz)
# We enable coord search and spectra plot creation
btnSpectraDisable=false
SpectraEnabled=true
end
end
# Image loaders based on the position of the current image (increment and decrement for both normal and filter)
@ -389,8 +460,8 @@ end
# Append a query string to force the image to refresh
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)
@ -408,8 +479,8 @@ end
# Append a query string to force the image to refresh
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)
@ -454,8 +525,8 @@ end
current_triq=new_msi
current_col_triq=new_col_msi
imgIntT="/$(current_triq)"
colorbarT="/$(current_col_triq)"
imgIntT="/$(current_triq)?t=$(timestamp)"
colorbarT="/$(current_col_triq)?t=$(timestamp)"
text_nmass=replace(current_triq, "TrIQ_" => "")
text_nmass=replace(text_nmass, ".bmp" => "")
@ -474,6 +545,7 @@ end
progressPlot=true
btnPlotDisable=true
btnStartDisable=true
btnSpectraDisable=true
try
img=load(var)
#println("Image type:", typeof(img))
@ -528,7 +600,6 @@ end
), 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
@ -549,6 +620,11 @@ end
progressPlot=false
btnPlotDisable=false
btnStartDisable=false
if isfile(full_routeMz)
# We enable coord search and spectra plot creation
btnSpectraDisable=false
SpectraEnabled=true
end
end
# 3d plot for TrIQ
@onbutton triq3dPlot begin
@ -562,6 +638,7 @@ end
progressPlot=true
btnPlotDisable=true
btnStartDisable=true
btnSpectraDisable=true
try
img=load(var)
img_gray=Gray.(img) # Convert to grayscale
@ -610,7 +687,6 @@ end
), 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
@ -631,6 +707,11 @@ end
progressPlot=false
btnPlotDisable=false
btnStartDisable=false
if isfile(full_routeMz)
# We enable coord search and spectra plot creation
btnSpectraDisable=false
SpectraEnabled=true
end
end
# Contour 2d plot
@ -645,6 +726,7 @@ end
progressPlot=true
btnPlotDisable=true
btnStartDisable=true
btnSpectraDisable=true
try
img=load(var)
# Convert to grayscale
@ -665,8 +747,13 @@ end
layoutContour=PlotlyBase.Layout(
title="2D Topographic Map",
xaxis_title="X",
yaxis_title="Y"
xaxis=PlotlyBase.attr(
title="X",
scaleanchor="y"
),
yaxis=PlotlyBase.attr(
title="Y"
),
)
traceContour=PlotlyBase.contour(
z=elevation_smoothed,
@ -677,8 +764,6 @@ end
)
plotdataC=[traceContour]
plotlayoutC=layoutContour
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
@ -699,6 +784,11 @@ end
progressPlot=false
btnPlotDisable=false
btnStartDisable=false
if isfile(full_routeMz)
# We enable coord search and spectra plot creation
btnSpectraDisable=false
SpectraEnabled=true
end
end
# Contour 2d plot for TrIQ
@onbutton triqCPlot begin
@ -712,6 +802,7 @@ end
progressPlot=true
btnPlotDisable=true
btnStartDisable=true
btnSpectraDisable=true
try
img=load(var)
# Convert to grayscale
@ -732,8 +823,13 @@ end
layoutContour=PlotlyBase.Layout(
title="2D Topographic Map",
xaxis_title="X",
yaxis_title="Y"
xaxis=PlotlyBase.attr(
title="X",
scaleanchor="y"
),
yaxis=PlotlyBase.attr(
title="Y"
),
)
traceContour=PlotlyBase.contour(
z=elevation_smoothed,
@ -744,8 +840,6 @@ end
)
plotdataC=[traceContour]
plotlayoutC=layoutContour
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
@ -766,19 +860,67 @@ end
progressPlot=false
btnPlotDisable=false
btnStartDisable=false
if isfile(full_routeMz)
# We enable coord search and spectra plot creation
btnSpectraDisable=false
SpectraEnabled=true
end
end
@onbutton compareBtn begin
CompareDialog=true
# We remove the red lines
traceSpectra=PlotlyBase.scatter(x=xSpectraMz, y=ySpectraMz, mode="lines",name="Spectra",showlegend=false)
plotdata=[traceSpectra]
end
# Event detection for clicking on the spectrum plot
@onchange data_click begin
println("Clicked data on sum spectrum plot : ", data_click)
# Now it needs to compare if there is a value from the spectrum close (to make sure it does not select invalid m/z)
# and then, add it to the mass-to-charge ratio of interest input to the frontend to ease with inputs
# optional: red line signaling which m/z got selected in the spectrum plot
if !isempty(xSpectraMz)
#println("Clicked data on sum spectrum plot : ", data_click)
spectracoords=reshape(plotdata, 1, length(plotdata))
#println("Spectra: $(ndims(spectracoords))")
# Extract x and y values from data_click
cursor_data=data_click["cursor"]
x_value = cursor_data["x"]
y_value = cursor_data["y"] # Get the x and y values from the click of the cursor
closest_distance = Inf
for val in spectracoords
# Find the index where x is within a range
start_idx = findfirst(x -> x >= x_value - 10, val[:x])
end_idx = findlast(x -> x <= x_value + 10, val[:x])
# Ensure the index are valid and within range
if start_idx !== nothing && end_idx !== nothing
for i in start_idx:end_idx
spectra_x = val[:x][i]
spectra_y = val[:y][i]
distance = sqrt((spectra_x - x_value)^2 + (spectra_y - y_value)^2) # Calculate distance
if distance < closest_distance
closest_distance = distance
Nmass = round(spectra_x, digits=2)
end
end
end
end
layoutSpectra=PlotlyBase.Layout(
title="SUM Spectrum plot",
xaxis=PlotlyBase.attr(
title="<i>m/z</i>",
showgrid=true
),
yaxis=PlotlyBase.attr(
title="Intensity",
showgrid=true
),
autosize=false
)
traceSpectra=PlotlyBase.scatter(x=xSpectraMz, y=ySpectraMz, mode="lines",name="Spectra",showlegend=false)
trace2=PlotlyBase.scatter(x=[Nmass, Nmass],y=[0, maximum(ySpectraMz)],mode="lines",line=attr(color="red", width=0.5),name="<i>m/z</i> selected",showlegend=false)
plotdata=[traceSpectra,trace2] # We add the data from spectra and the red line to the plot
plotlayout=layoutSpectra
end
end
# WIP add an x and y input and a plot to select pixels in an image and then calculate a plot (not the sum of plots)
@ -791,12 +933,12 @@ end
ccall(:malloc_trim, Int32, (Int32,), 0) # Ensure julia returns the freed memory to OS
end
end
# == Pages ==
# ==Pages ==
# Register a new route and the page that will be loaded on access
@page("/", "app.jl.html")
end
# == Advanced features ==
# ==Advanced features ==
#=
- 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

View File

@ -1,311 +1,354 @@
<template>
<header id="header">
<img src="/css/LABI_logo.jpeg" alt="Labi Logo Icon" id="imgLogo">
<div>
<h4>Julia mzML imzML analysis GUI&nbsp;</h4>
<h6>Please make sure the ibd, the mzML and the imzML files are located in the same directory and have the same name.</h6>
<h6>It may take a while to generate the image and the plot, please be patient.</h6>
<h6>To generate the contour or surface plots, you have to select the desired image first using the interface.</h6>
<header id="header">
<img src="/css/LABI_logo.jpeg" alt="Labi Logo Icon" id="imgLogo">
<div>
<h4>Julia mzML imzML analysis GUI&nbsp;</h4>
<h6>Please make sure the ibd, the mzML and the imzML files are located in the same directory and have the same
name.</h6>
<h6>It may take a while to generate the image and the plot, please be patient.</h6>
<h6>To generate the contour or surface plots, you have to select the desired image first using the interface.</h6>
</div>
</header>
<div id="extDivStyle" class="row col-12 q-pa-xl">
<div class="row col-6">
<!-- Left DIV -->
<div id="intDivStyle" class="st-col col-12 st-module">
<!--<q-input id="textRoute" standout="custom-standout" v-model="file_route" label="Insert the route to your imzML file"></q-input>-->
<h6>Search for your imzML file in your device</h6>
<q-btn id="btnStyle" icon="search" class="q-ma-sm" v-on:click="btnSearch=true"
label="Search in your device for the imzML file"></q-btn>
<!--<p>{{full_route}}</p>-->
<div class="row st-col col-12">
<!--<q-input id="textName" class="col-9" standout="custom-standout" v-model="file_name" label="Insert the name of your imzML file"></q-input>-->
<q-btn-dropdown id="btnStyle" class="q-ma-sm" :loading="progressPlot" :disable="btnPlotDisable"
label="Generate Plots" icon="play_arrow">
<template v-slot:loading>
<q-spinner-hourglass class="on-left" />
Loading Plot
</template>
<q-list>
<q-item clickable v-close-popup v-on:click="imageCPlot=true">
<q-item-section>
<q-item-label>Image Contour Plot</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup v-on:click="triqCPlot=true">
<q-item-section>
<q-item-label>TrIQ Contour Plot</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup v-on:click="image3dPlot=true">
<q-item-section>
<q-item-label>Image 3D Plot</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup v-on:click="triq3dPlot=true">
<q-item-section>
<q-item-label>TrIQ 3D Plot</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</div>
</header>
<div id="extDivStyle" class="row col-12 q-pa-xl">
<div class="row col-7">
<!-- Left DIV -->
<div id="intDivStyle" class="st-col col-12 st-module">
<!--<q-file v-model="file_route" filled="" label="Select your imzML file" accept=".imzML"></q-file>-->
<!--<q-input id="textRoute" standout="custom-standout" v-model="file_route" label="Insert the route to your imzML file"></q-input>-->
<h6>Search for your imzML file in your device</h6>
<q-btn id="btnStyle" icon="search" class="q-ma-sm" v-on:click="btnSearch=true" label="Search in your device for the imzML file"></q-btn>
<!--<p>{{full_route}}</p>-->
<div class="row st-col col-12">
<!--<q-input id="textName" class="col-9" standout="custom-standout" v-model="file_name" label="Insert the name of your imzML file"></q-input>-->
<q-btn-dropdown
id="btnStyle"
class="q-ma-sm"
:loading="progressPlot"
:disable="btnPlotDisable"
label="Generate Plots"
icon="play_arrow"
>
<template v-slot:loading>
<q-spinner-hourglass class="on-left" />
Loading Plot
</template>
<q-list>
<q-item clickable v-close-popup v-on:click="createSumPlot=true">
<q-item-section>
<q-item-label>Sum Spectrum Plot</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup v-on:click="imageCPlot=true">
<q-item-section>
<q-item-label>Image Contour Plot</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup v-on:click="triqCPlot=true">
<q-item-section>
<q-item-label>TrIQ Contour Plot</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup v-on:click="image3dPlot=true">
<q-item-section>
<q-item-label>Image 3D Plot</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup v-on:click="triq3dPlot=true">
<q-item-section>
<q-item-label>TrIQ 3D Plot</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</div>
<p id="lblFullRoute">full route: {{full_route}} {{warning_fr}}</p>
<!-- Variable Manipulation -->
<div class="row">
<div class="st-col col-12 col-sm">
<q-input standout="custom-standout" id="textNmass" step="0.01" v-model="Nmass" label="Mass-to-charge ratio of interest" type="number" :rules="[ val => !!val || '* Required', val => val >= 0.0 &amp;&amp; val <= 2000.0 || 'Need positive mass values',]"></q-input>
</div>
<div class="st-col col-12 col-sm">
<q-input standout="custom-standout" id="textTol" step="0.01" v-model="Tol" label="Mass-to-charge ratio tolerance" type="number" :rules="[val => !!val || '* Required', val => val >= 0.0 &amp;&amp; val <= 1.0 || 'Needs to be in range between 0 and 1',]"></q-input>
</div>
</div>
<div class="row">
<div class="st-col col-12 col-sm">
<q-toggle id="btnEnableTriq" v-on:click="triqEnabled" v-model="triqEnabled" color="blue" label="Add Threshold Intensity Quantization (TrIQ)!"></q-toggle>
</div>
</div>
<!-- Triq Variable Manipulation -->
<div class="row">
<div class="st-col col-12 col-sm-8">
<q-input standout="custom-standout" id="textTriqProb" step="0.01" v-model="triqProb" label="TrIQ probability" type="number" :rules="[
val => triqEnabled ? ( '* Required', val >= 0 &amp;&amp; val <= 1 || 'Needs to be in range between 0 and 1') : true
]" :readonly="!triqEnabled" :disable="!triqEnabled"></q-input>
</div>
<div class="st-col col-12 col-sm-4">
<q-input standout="custom-standout" id="textTriqColor" step="1" v-model="triqColor" label="TrIQ color levels" type="number" :rules="[
val => triqEnabled ? ( '* Required', val >= 0 &amp;&amp; val <= 256 || 'Needs to be in range between 1 and 256') : true
]" :readonly="!triqEnabled" :disable="!triqEnabled"></q-input>
</div>
</div>
<div class="row">
<q-btn id="btnStyle" :loading="progress" class="q-ma-sm" :disabled="btnStartDisable" icon="play_arrow" v-on:click="mainProcess=true" padding="lg" label="Main process">
<template v-slot:loading>
<q-spinner-hourglass class="on-left" />
Loading...
</template>
</q-btn>
<q-btn id="btnStyle" icon="zoom_out_map" class="q-ma-sm on-right" v-on:click="compareBtn=true" padding="sm" label="Compare"></q-btn>
</div>
<p>{{msg}}</p>
</div>
</div>
<div class="row col-5">
<!-- Right DIV -->
<div id="intDivStyle" class="st-col col-12 col-sm st-module">
<st-tabs id="tabHeader":ids="tabIDs" :labels="tabLabels" v-model="selectedTab" no-arrows></st-tabs>
<q-tab-panels v-model="selectedTab">
<q-tab-panel name="tab0">
<!-- Content for Tab 0 -->
<!-- Btn image changer -->
<h6>Image Visualizer</h6>
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinus=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlus=true"></q-btn>
</div>
<!-- Image manager -->
<div id="image-container" class="row st-col col-12 items-center">
<div class="st-col col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgInt" fit="scale-down"></q-img>
</div>
<div class="st-col col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbar"></q-img>
</div>
</div>
<p>{{msgimg}}</p>
</q-tab-panel>
<q-tab-panel name="tab1">
<!-- Content for Tab 1 -->
<!-- Triq Btn image changer -->
<h6>TrIQ Visualizer</h6>
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinusT=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlusT=true"></q-btn>
</div>
<!-- Triq Image manager -->
<div id="image-container" class="row st-col col-12 items-center">
<div class="col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgIntT" fit="scale-down"></q-img>
</div>
<div class="col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbarT"></q-img>
</div>
</div>
<p>{{msgtriq}}</p>
</q-tab-panel>
<q-tab-panel name="tab2">
<!-- Content for Tab 2 -->
<!--<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" class="q-pa-none q-ma-none"></plotly>-->
<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" @click="data_click" class="q-pa-none q-ma-none sync_data"></plotly>
</q-tab-panel>
<q-tab-panel name="tab3">
<!-- Content for Tab 3 -->
<plotly id="plotStyle" :data="plotdataC" :layout="plotlayoutC" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab4">
<!-- Content for Tab 4 -->
<plotly id="plotStyle3d" :data="plotdata3d" :layout="plotlayout3d" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
</q-tab-panels>
</div>
</div>
<p id="lblFullRoute">full route: {{full_route}}</p>
<!-- Variable Manipulation -->
<div class="row">
<div class="st-col col-12 col-sm q-ma-sm">
<q-input standout="custom-standout" id="textNmass" step="0.01" v-model="Nmass"
label="Mass-to-charge ratio of interest" type="number"
:rules="[ val => !!val || '* Required', val => val >= 0.0 &amp;&amp; val <= 2000.0 || 'Need positive mass values',]"></q-input>
</div>
<div class="st-col col-12 col-sm q-ma-sm">
<q-input standout="custom-standout" id="textTol" step="0.01" v-model="Tol"
label="Mass-to-charge ratio tolerance" type="number"
:rules="[val => !!val || '* Required', val => val >= 0.0 &amp;&amp; val <= 1.0 || 'Needs to be in range between 0 and 1',]"></q-input>
</div>
</div>
<q-dialog v-model="warning_msg">
<q-card>
<q-card-section>
<div class="text-h6">Warning</div>
</q-card-section>
<q-card-section class="q-pt-none">
{{msg}}
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="Ok" style="color:#009f90" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="CompareDialog" full-width>
<q-card>
<q-card-section>
<div class="text-h6">Compare two diferent images or plots in a larger screen</div>
</q-card-section>
<q-card-section class="q-pt-none col-12">
<div class="row">
<!-- Triq Variable Manipulation -->
<div class="col-6">
<div class="st-col col-6 col-sm q-ma-sm">
<q-toggle id="btnEnableTriq" v-on:click="triqEnabled" v-model="triqEnabled" color="blue"
label="Add Threshold Intensity Quantization (TrIQ)!"></q-toggle>
</div>
<div class="row">
<div class="col-6">
<st-tabs id="tabHeader":ids="tabIDs" :labels="tabLabels" v-model="selectedTab"></st-tabs>
<q-tab-panels v-model="selectedTab">
<q-tab-panel name="tab0">
<!-- Content for Tab 0 -->
<!-- Btn image changer -->
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinus=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlus=true"></q-btn>
</div>
<!-- Image manager -->
<div id="image-container" class="row st-col col-12 items-center">
<div class="st-col col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgInt" fit="scale-down"></q-img>
</div>
<div class="st-col col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbar"></q-img>
</div>
</div>
<p>{{msgimg}}</p>
</q-tab-panel>
<q-tab-panel name="tab1">
<!-- Content for Tab 1 -->
<!-- Triq Btn image changer -->
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinusT=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlusT=true"></q-btn>
</div>
<!-- Triq Image manager -->
<div id="image-container" class="row st-col col-12 items-center">
<div class="col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgIntT" fit="scale-down"></q-img>
</div>
<div class="col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbarT"></q-img>
</div>
</div>
<p>{{msgtriq}}</p>
</q-tab-panel>
<q-tab-panel name="tab2">
<!-- Content for Tab 2 -->
<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab3">
<!-- Content for Tab 3 -->
<plotly id="plotStyle" :data="plotdataC" :layout="plotlayoutC" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab4">
<!-- Content for Tab 4 -->
<plotly id="plotStyle3d" :data="plotdata3d" :layout="plotlayout3d" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
</q-tab-panels>
</div>
<div class="col-6">
<st-tabs id="tabHeader" :ids="CompTabIDs" :labels="CompTabLabels" v-model="CompSelectedTab" outside-arrows mobile-arrows></st-tabs>
<q-tab-panels v-model="CompSelectedTab">
<q-tab-panel name="tab0">
<!-- Content for Tab 0 -->
<!-- Btn image changer -->
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinus=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlus=true"></q-btn>
</div>
<!-- Image manager -->
<div id="image-container" class="row st-col col-12 items-center">
<div class="st-col col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgInt" fit="scale-down"></q-img>
</div>
<div class="st-col col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbar"></q-img>
</div>
</div>
<p>{{msgimg}}</p>
</q-tab-panel>
<q-tab-panel name="tab1">
<!-- Content for Tab 1 -->
<!-- Triq Btn image changer -->
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinusT=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlusT=true"></q-btn>
</div>
<!-- Triq Image manager -->
<div id="image-container" class="row st-col col-12 items-center">
<div class="col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgIntT" fit="scale-down"></q-img>
</div>
<div class="col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbarT"></q-img>
</div>
</div>
<p>{{msgtriq}}</p>
</q-tab-panel>
<q-tab-panel name="tab2">
<!-- Content for Tab 2 -->
<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab3">
<!-- Content for Tab 3 -->
<plotly id="plotStyle" :data="plotdataC" :layout="plotlayoutC" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab4">
<!-- Content for Tab 4 -->
<plotly id="plotStyle3d" :data="plotdata3d" :layout="plotlayout3d" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
</q-tab-panels>
</div>
<div class="st-col col-4 col-sm-4 q-ma-sm">
<q-input standout="custom-standout" id="textTriqProb" step="0.01" v-model="triqProb"
label="TrIQ probability" type="number" :rules="[
val => triqEnabled ? ( '* Required', val >= 0 &amp;&amp; val <= 1 || 'Needs to be in range between 0 and 1') : true
]" :readonly="!triqEnabled" :disable="!triqEnabled"></q-input>
</div>
<div class="st-col col-4 col-sm-4 q-ma-sm">
<q-input standout="custom-standout" id="textTriqColor" step="1" v-model="triqColor"
label="TrIQ color levels" type="number" :rules="[
val => triqEnabled ? ( '* Required', val >= 0 &amp;&amp; val <= 256 || 'Needs to be in range between 1 and 256') : true
]" :readonly="!triqEnabled" :disable="!triqEnabled"></q-input>
</div>
</div>
</q-card-section>
</div>
<!-- Spectra Plot Manipulation -->
<div class="col-6">
<div class="st-col col-6 col-sm">
<q-btn-dropdown id="btnStyle" class="q-ma-sm" :loading="progressSpectraPlot" :disable="btnSpectraDisable"
label="Generate Spectra" icon="play_arrow">
<template v-slot:loading>
<q-spinner-hourglass class="on-left" />
Loading Plot
</template>
<q-card-actions align="right">
<q-btn flat label="Done" style="color:#009f90" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
<q-list>
<q-item clickable v-close-popup v-on:click="createSumPlot=true">
<q-item-section>
<q-item-label>Sum Spectrum Plot</q-item-label>
</q-item-section>
</q-item>
<q-item clickable v-close-popup v-on:click="createXYPlot=true">
<q-item-section>
<q-item-label>Spectrum Plot (X,Y)</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</div>
<div class="row col-6">
<div class="st-col col-4 col-sm-4 q-ma-sm">
<q-input standout="custom-standout" step="1" v-model="xCoord" label="X coord"
type="number" :rules="[
val => SpectraEnabled ? ( '* Required', val >= 0|| 'Needs to be bigger than 0') : true
]" :readonly="!SpectraEnabled" :disable="!SpectraEnabled"></q-input>
</div>
<div class="st-col col-4 col-sm-4 q-ma-sm">
<q-input standout="custom-standout" step="1" v-model="yCoord" label="Y coord"
type="number" :rules="[
val => SpectraEnabled ? ( '* Required', val <= 0|| 'Needs to be lower than 0') : true
]" :readonly="!SpectraEnabled" :disable="!SpectraEnabled"></q-input>
</div>
</div>
</div>
</div>
<div class="row">
<q-btn id="btnStyle" :loading="progress" class="q-ma-sm" :disabled="btnStartDisable" icon="play_arrow"
v-on:click="mainProcess=true" padding="lg" label="Main process">
<template v-slot:loading>
<q-spinner-hourglass class="on-left" />
Loading...
</template>
</q-btn>
<q-btn id="btnStyle" icon="zoom_out_map" class="q-ma-sm on-right" v-on:click="compareBtn=true" padding="sm"
label="Compare"></q-btn>
</div>
<p>{{msg}}</p>
</div>
</div>
<div class="row col-6">
<!-- Right DIV -->
<div id="intDivStyle" class="st-col col-12 col-sm st-module">
<st-tabs id="tabHeader" :ids="tabIDs" :labels="tabLabels" v-model="selectedTab" no-arrows></st-tabs>
<q-tab-panels v-model="selectedTab">
<q-tab-panel name="tab0">
<!-- Content for Tab 0 -->
<!-- Btn image changer -->
<h6>Image Visualizer</h6>
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinus=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlus=true"></q-btn>
</div>
<!-- Image manager -->
<div id="image-container" class="row st-col col-12">
<div class="col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgInt" width="80%"></q-img>
</div>
<div class="col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbar"></q-img>
</div>
</div>
<p>{{msgimg}}</p>
</q-tab-panel>
<q-tab-panel name="tab1">
<!-- Content for Tab 1 -->
<!-- Triq Btn image changer -->
<h6>TrIQ Visualizer</h6>
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinusT=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlusT=true"></q-btn>
</div>
<!-- Triq Image manager -->
<div id="image-container" class="row st-col col-12">
<div class="col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgIntT" width="80%"></q-img>
</div>
<div class="col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbarT"></q-img>
</div>
</div>
<p>{{msgtriq}}</p>
</q-tab-panel>
<q-tab-panel name="tab2">
<!-- Content for Tab 2 -->
<!--<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" class="q-pa-none q-ma-none"></plotly>-->
<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" @click="data_click"
class="q-pa-none q-ma-none sync_data"></plotly>
</q-tab-panel>
<q-tab-panel name="tab3">
<!-- Content for Tab 3 -->
<plotly id="plotStyle" :data="plotdataC" :layout="plotlayoutC" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab4">
<!-- Content for Tab 4 -->
<plotly id="plotStyle3d" :data="plotdata3d" :layout="plotlayout3d" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
</q-tab-panels>
</div>
</div>
</div>
<q-dialog v-model="warning_msg">
<q-card>
<q-card-section>
<div class="text-h6">Warning</div>
</q-card-section>
<q-card-section class="q-pt-none">
{{msg}}
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="Ok" style="color:#009f90" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog v-model="CompareDialog" full-width>
<q-card>
<q-card-section>
<div class="text-h6">Compare two diferent images or plots in a larger screen</div>
</q-card-section>
<q-card-section class="q-pt-none col-12">
<div class="row">
<div class="col-6">
<st-tabs id="tabHeader" :ids="tabIDs" :labels="tabLabels" v-model="selectedTab"></st-tabs>
<q-tab-panels v-model="selectedTab">
<q-tab-panel name="tab0">
<!-- Content for Tab 0 -->
<!-- Btn image changer -->
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinus=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlus=true"></q-btn>
</div>
<!-- Image manager -->
<div id="image-container" class="row st-col col-12">
<div class="st-col col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgInt" width="80%"></q-img>
</div>
<div class="st-col col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbar"></q-img>
</div>
</div>
<p>{{msgimg}}</p>
</q-tab-panel>
<q-tab-panel name="tab1">
<!-- Content for Tab 1 -->
<!-- Triq Btn image changer -->
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinusT=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlusT=true"></q-btn>
</div>
<!-- Triq Image manager -->
<div id="image-container" class="row st-col col-12">
<div class="col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgIntT" width="80%"></q-img>
</div>
<div class="col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbarT"></q-img>
</div>
</div>
<p>{{msgtriq}}</p>
</q-tab-panel>
<q-tab-panel name="tab2">
<!-- Content for Tab 2 -->
<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab3">
<!-- Content for Tab 3 -->
<plotly id="plotStyle" :data="plotdataC" :layout="plotlayoutC" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab4">
<!-- Content for Tab 4 -->
<plotly id="plotStyle3d" :data="plotdata3d" :layout="plotlayout3d" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
</q-tab-panels>
</div>
<div class="col-6">
<st-tabs id="tabHeader" :ids="CompTabIDs" :labels="CompTabLabels" v-model="CompSelectedTab" outside-arrows
mobile-arrows></st-tabs>
<q-tab-panels v-model="CompSelectedTab">
<q-tab-panel name="tab0">
<!-- Content for Tab 0 -->
<!-- Btn image changer -->
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinus=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlus=true"></q-btn>
</div>
<!-- Image manager -->
<div id="image-container" class="row st-col col-12">
<div class="st-col col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgInt" width="80%"></q-img>
</div>
<div class="st-col col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbar"></q-img>
</div>
</div>
<p>{{msgimg}}</p>
</q-tab-panel>
<q-tab-panel name="tab1">
<!-- Content for Tab 1 -->
<!-- Triq Btn image changer -->
<div>
<q-btn id="btnStyle" icon="arrow_back" class="q-my-sm" v-on:click="imgMinusT=true"></q-btn>
<q-btn id="btnStyle" icon="arrow_forward" class="q-my-sm on-right" v-on:click="imgPlusT=true"></q-btn>
</div>
<!-- Triq Image manager -->
<div id="image-container" class="row st-col col-12">
<div class="col-10">
<q-img id="imgInt" class="q-ma-none q-pa-none" :src="imgIntT" width="80%"></q-img>
</div>
<div class="col-2">
<q-img id="colorbar" class="q-ma-none q-pa-none" :src="colorbarT"></q-img>
</div>
</div>
<p>{{msgtriq}}</p>
</q-tab-panel>
<q-tab-panel name="tab2">
<!-- Content for Tab 2 -->
<plotly id="plotStyle" :data="plotdata" :layout="plotlayout" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab3">
<!-- Content for Tab 3 -->
<plotly id="plotStyle" :data="plotdataC" :layout="plotlayoutC" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
<q-tab-panel name="tab4">
<!-- Content for Tab 4 -->
<plotly id="plotStyle3d" :data="plotdata3d" :layout="plotlayout3d" class="q-pa-none q-ma-none"></plotly>
</q-tab-panel>
</q-tab-panels>
</div>
</div>
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="Done" style="color:#009f90" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
</template>

View File

@ -4,8 +4,7 @@ PENDING
Create function that makes the imzML from mzML files ?
Possibility to add multiple imzML to process at once ?
Per pixel of image plot creation for spectra
Multiple spectra plot types
Even faster initial boot and subsectuential boot
Add comparison image (rotate, transform, translate, transparency) CURRENTLY ONGOING
DONE
Quicker start for julia GUI
@ -19,8 +18,10 @@ DONE
3d topology plots for images
2d contour plots for images
Image flip upside down
Tag for time it takes in creating image and creating plots
Measure for the time it takes creating image or plot
Rotate vertical images
Easier input for files
TrIQ default values
Comparative for two views
Even faster initial boot and subsectuential boot
Multiple spectra plot types

View File

@ -1,13 +1,25 @@
using Pkg
Pkg.activate(".")
Pkg.instantiate()
Pkg.update()
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")
Pkg.add("StipplePlotly")
packages = [
"GenieFramework", "Libz", "PlotlyBase", "CairoMakie", "Colors",
"Statistics", "NaturalSort", "Genie",
"Images", "LinearAlgebra", "NativeFileDialog", "StipplePlotly"
]
# Check for missing packages
for pkg in packages
if !(pkg in keys(Pkg.dependencies()))
Pkg.add(pkg)
end
end
# Add library for mzML imzML from GitHub if missing
if !("julia_mzML_imzML" in keys(Pkg.dependencies()))
Pkg.add(url="https://github.com/CINVESTAV-LABI/julia_mzML_imzML")
end
using Genie
@ -27,3 +39,5 @@ Genie.loadapp()
@async run(`start $url`) # For Windows
end
end
wait()