From df0d82910b0efc1826f0aa6528a70fea8e585154 Mon Sep 17 00:00:00 2001 From: Pixelguy14 Date: Wed, 29 Jan 2025 15:55:30 -0600 Subject: [PATCH 1/3] Alternative versions of SaveBitMap and IntQuant for adjustments to the color level input --- app.jl | 64 +++++++++++++++++++------------------------ app.jl.html | 22 +++++++++------ julia_imzML_visual.jl | 64 +++++++++++++++++++++++++++++++++++++++++++ start_MSI_GUI.jl | 2 ++ 4 files changed, 107 insertions(+), 45 deletions(-) create mode 100644 julia_imzML_visual.jl diff --git a/app.jl b/app.jl index 47fe52c..b5c155d 100644 --- a/app.jl +++ b/app.jl @@ -13,6 +13,7 @@ using Images using LinearAlgebra using NativeFileDialog # Opens the file explorer depending on the OS using StipplePlotly +include("./julia_imzML_visual.jl") @genietools # == Code import == @@ -54,13 +55,13 @@ function loadImgPlot(interfaceImg::String) cleaned_img=lstrip(cleaned_img, '/') var=joinpath("./public", cleaned_img) img=load(var) - println("type of img: $(typeof(img))") + #println("type of img: $(typeof(img))") # Convert to grayscale img_gray=Gray.(img) img_array=Array(img_gray) #println(typeof(img_array)) elevation=Float32.(Array(img_array)) ./ 255.0 - println("type of elevation: $(typeof(elevation))") + #println("type of elevation: $(typeof(elevation))") # Get the X, Y coordinates of the image height, width=size(img_array) #println("height: $(height), width: $(width)") @@ -203,10 +204,12 @@ function loadSurfacePlot(interfaceImg::String) aspectratio=aspect_ratio ) ) + # Transpose the elevation_smoothed array if Y axis is longer than X axis to fix chopping + elevation_smoothed=transpose(elevation_smoothed) 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 + else + X=-X end trace3D=PlotlyBase.surface( @@ -244,7 +247,7 @@ function crossLinesPlot(x, y, maxwidth, maxheight) end # == Reactive code == -# reactive code to make the UI interactive +# Reactive code to make the UI interactive @app begin # == Reactive variables == # reactive variables exist in both the Julia backend and the browser with two-way synchronization @@ -476,6 +479,7 @@ end end @onbutton mainProcess begin + #@onchange Nmass begin progress=true # Start progress button animation btnStartDisable=true # We disable the button to avoid multiple requests btnPlotDisable=true @@ -489,25 +493,21 @@ end 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=(140, 440)) # Container + fig=CairoMakie.Figure(size=(128, 256)) # Container # Append a query string to force the image to refresh timestamp=string(time_ns()) if triqEnabled # If we have TrIQ - if colorLevel < 4 || colorLevel > 256 || triqProb < 0.8 || triqProb > 1 + if colorLevel < 2 || colorLevel > 256 || triqProb < 0.8 || triqProb > 1 msg="Incorrect TrIQ values, please adjust accordingly and try again." warning_msg=true else image_path=joinpath("./public", "TrIQ_$(text_nmass).bmp") - SaveBitmap(joinpath("public", "TrIQ_$(text_nmass).bmp"),TrIQ(slice, Int(colorLevel), triqProb),ViridisPalette) - # Flip te image vertically then save it again - img=load(image_path) - if size(img, 1) > size(img, 2) # fix to taller images - img=reverse(permutedims(img, (2, 1)), dims=1) - end - flipped_img=reverse(img, dims=1) - imgWidth=size(flipped_img, 2) - imgHeight=size(flipped_img, 1) - save(image_path, flipped_img) + sliceTriq=TrIQ(slice, Int(colorLevel), triqProb) + #println("slice raw: $(typeof(slice))") + #println("TriQ matrix: $(typeof(sliceTriq))") + sliceTriq=reverse(sliceTriq, dims=2) + ##SaveBitmap(joinpath("public", "TrIQ_$(text_nmass).bmp"),sliceTriq,ViridisPalette) + SaveBitmapCl(joinpath("public", "TrIQ_$(text_nmass).bmp"),sliceTriq,ViridisPalette) # Use timestamp to refresh image interface container imgIntT="/TrIQ_$(text_nmass).bmp?t=$(timestamp)" plotdataImgT, plotlayoutImgT, imgWidth, imgHeight=loadImgPlot(imgIntT) @@ -515,12 +515,8 @@ end 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(colorLevel), triqProb)), length=10), sigdigits=3) - #println("ticks: $(round.(range(0, stop=maximum(TrIQ(slice, Int(colorLevel), triqProb)), length=10), sigdigits=3))") - ticks=round.(range(0, (stop=maximum(slice)*triqProb), length=15), sigdigits=3) - #println("ticks 2: $(round.(range(0, (stop=maximum(slice)*triqProb), length=15), sigdigits=3))") - #Colorbar(fig[1, 1], colormap=rgb_ViridisPalette, limits=(0, maximum(TrIQ(slice, Int(colorLevel), triqProb))),ticks=ticks, label="Intensity") - Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)*triqProb),ticks=ticks, label="Intensity", size = 25) + ticks=round.(range(0, (stop=maximum(sliceTriq)*triqProb), length=15), sigdigits=3) + Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(sliceTriq)*triqProb),ticks=ticks, label="Intensity", size = 25) save("public/colorbar_TrIQ_$(text_nmass).png", fig) colorbarT="/colorbar_TrIQ_$(text_nmass).png?t=$(timestamp)" # Get current colorbar @@ -537,16 +533,13 @@ end end else # If we don't use TrIQ 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) - if size(img, 1) > size(img, 2) # fix to taller images - img=reverse(permutedims(img, (2, 1)), dims=1) - end - flipped_img=reverse(img, dims=1) - imgWidth=size(flipped_img, 2) - imgHeight=size(flipped_img, 1) - save(image_path, flipped_img) + ##sliceQuant=IntQuant(slice) + sliceQuant=IntQuantCl(slice,colorLevel) + #println("slice raw: $(typeof(slice))") + #println("slice in intQuant: $(typeof(sliceQuant))") + sliceQuant=reverse(sliceQuant, dims=2) + ##SaveBitmap(joinpath("public", "MSI_$(text_nmass).bmp"),sliceQuant,ViridisPalette) + SaveBitmapCl(joinpath("public", "MSI_$(text_nmass).bmp"),sliceQuant,ViridisPalette) # Use timestamp to refresh image interface container imgInt="/MSI_$(text_nmass).bmp?t=$(timestamp)" plotdataImg, plotlayoutImg, imgWidth, imgHeight=loadImgPlot(imgInt) @@ -555,9 +548,8 @@ end msgimg="Image with the Nmass of $(replace(text_nmass, "_" => "."))" # Create colorbar #ticks=round.(range(0, stop=maximum(slice), length=10), sigdigits=3) - ticks=round.(range(0, stop=maximum(slice), length=15), sigdigits=3) - #Colorbar(fig[1, 1], colormap=rgb_ViridisPalette, limits=(0, maximum(slice)),ticks=ticks, label="Intensity") - Colorbar(fig[1, 1], colormap=cgrad(:viridis, 256, categorical=true), limits=(0, maximum(slice)),ticks=ticks, label="Intensity", size = 25) + ticks=round.(range(0, stop=maximum(sliceQuant), length=15), sigdigits=3) + Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(sliceQuant)),ticks=ticks, label="Intensity", size = 25) save("public/colorbar_MSI_$(text_nmass).png", fig) colorbar="/colorbar_MSI_$(text_nmass).png?t=$(timestamp)" # Get current colorbar diff --git a/app.jl.html b/app.jl.html index 34c3478..3d2b22d 100644 --- a/app.jl.html +++ b/app.jl.html @@ -57,21 +57,29 @@

full route: {{full_route}}

-
+
-
+
+
+ +
- +
+
@@ -82,12 +90,8 @@ val => triqEnabled ? ( '* Required', val >= 0.8 && val <= 1 || 'Needs to be in range between 0.8 and 1') : true ]" :readonly="!triqEnabled" :disable="!triqEnabled">
-
- -
+
diff --git a/julia_imzML_visual.jl b/julia_imzML_visual.jl new file mode 100644 index 0000000..a4d5fdb --- /dev/null +++ b/julia_imzML_visual.jl @@ -0,0 +1,64 @@ +# IntQuantCl is originally a function of julia mzMl imzML with the adition +# of altering the scale of the colors according to colorlevel. +function IntQuantCl( slice , colorLevel) + # Compute scale factor for amplitude discretization + lower = minimum( slice ) + scale = colorLevel / maximum( slice ) + dim = size( slice ) + image = zeros( UInt8, dim[1], dim[2] ) + for i in 1:length( slice ) + image[i] = convert( UInt8, floor( slice[i] * scale + 0.5 ) ) + end + return image +end + +# SaveBitmap is also originally a function of the mzML imzML library in julia, +# This function dinamically adjust the color palete adjusting to the ammount of colors +# available in pixmap +function SaveBitmapCl( name, + pixMap::Array{UInt8,2}, + colorTable::Array{UInt32,1} ) + # Get image dimensions + dim = size( pixMap ) + if length( dim ) != 2 + return 0 + end + # Compute row padding + padding = ( 4 - dim[1] & 0x3 ) & 0x3 + # Compute file dimensions. Header = 14 + 40 + ( 256 * 4 ) = 1078 + offset = 1078 + imgBytes = dim[2] * ( dim[1] + padding ) + # Create file + stream = open( name, "w" ) + # Save file header + write( stream, UInt16( 0x4D42 ) ) + write( stream, UInt32[ offset + imgBytes, 0 , offset ] ) + # Save info header + write( stream, UInt32[ 40, dim[1], dim[2], 0x80001, 0 ] ) + write( stream, UInt32[ imgBytes, 0, 0, 256, 0 ] ) + # Get unique colors displayed in pixMap + unique_colors = unique(vec(pixMap)) + n_colors = length(unique_colors) + # Color levels can't surpass 256 + levels = min(n_colors, 256) + extendedColorTable = zeros(UInt32, 256) + for i in 1:256 + idx = ceil(Int, i * levels / 256) + extendedColorTable[i] = colorTable[idx] + end + write(stream, extendedColorTable) + # Save image pixels + if padding == 0 + for i = 1:dim[2] + write( stream, pixMap[:,i] ) + end + else + zeroPad = zeros( UInt8, padding ) + for i in 1:dim[2] + write( stream, pixMap[:,i] ) + write( stream, zeroPad ) + end + end + # Close file + close( stream ) +end \ No newline at end of file diff --git a/start_MSI_GUI.jl b/start_MSI_GUI.jl index f23f076..35cd8ee 100644 --- a/start_MSI_GUI.jl +++ b/start_MSI_GUI.jl @@ -3,6 +3,7 @@ Pkg.activate(".") Pkg.instantiate() Pkg.gc() +""" packages = [ "GenieFramework", "Libz", "PlotlyBase", "CairoMakie", "Colors", "Statistics", "NaturalSort", "Genie", @@ -20,6 +21,7 @@ end if !("julia_mzML_imzML" in keys(Pkg.dependencies())) Pkg.add(url="https://github.com/CINVESTAV-LABI/julia_mzML_imzML") end +""" using Genie From fdd625d3e069e478192581e5dff3381b20122aa8 Mon Sep 17 00:00:00 2001 From: Pixelguy14 Date: Thu, 30 Jan 2025 00:40:01 -0600 Subject: [PATCH 2/3] Bitmap is now normalized in creation, which evenly distributes colors of the colorTable better, now IntQuant allows for coloLevel adjustments --- README.md | 2 +- app.jl | 33 +++++++++++++++++++++++---------- app.jl.html | 10 ++++------ julia_imzML_visual.jl | 23 ++++++++++------------- start_MSI_GUI.jl | 4 +++- 5 files changed, 41 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 0d967b7..98e1b61 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ A Graphical User Interface for MSI in Julia: https://github.com/CINVESTAV-LABI/j ``` julia --project=. start_MSI_GUI.jl ``` -3. 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. +3. After the script has finished loading, You can open a page (http://127.0.0.1:1481/) in your browser with the web app running. Additional notes:
After the first boot initializes the packages in your computer, subsequent uses of the app should not take longer to load.
diff --git a/app.jl b/app.jl index b5c155d..73dd73f 100644 --- a/app.jl +++ b/app.jl @@ -13,6 +13,7 @@ using Images using LinearAlgebra using NativeFileDialog # Opens the file explorer depending on the OS using StipplePlotly +using Printf include("./julia_imzML_visual.jl") @genietools @@ -121,7 +122,8 @@ function loadContourPlot(interfaceImg::String) img=load(var) img_gray=Gray.(img) img_array=Array(img_gray) - elevation=Float32.(Array(img_gray)) ./ 255.0 # Normalize between 0 and 1 + # parse matrix to int32 to closely resemble similarity to original bitmap + elevation=int32.(Array(img_gray)) # Smooth the image sigma=3.0 @@ -487,7 +489,7 @@ end 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 && colorLevel > 1 && colorLevel < 257 msg="File exists, Nmass=$(Nmass) Tol=$(Tol). Loading file will begin, please be patient." try spectra=LoadImzml(full_route) @@ -497,12 +499,12 @@ end # Append a query string to force the image to refresh timestamp=string(time_ns()) if triqEnabled # If we have TrIQ - if colorLevel < 2 || colorLevel > 256 || triqProb < 0.8 || triqProb > 1 + if triqProb < 0.8 || triqProb > 1 msg="Incorrect TrIQ values, please adjust accordingly and try again." warning_msg=true else image_path=joinpath("./public", "TrIQ_$(text_nmass).bmp") - sliceTriq=TrIQ(slice, Int(colorLevel), triqProb) + sliceTriq=TrIQ(slice, colorLevel, triqProb) #println("slice raw: $(typeof(slice))") #println("TriQ matrix: $(typeof(sliceTriq))") sliceTriq=reverse(sliceTriq, dims=2) @@ -514,9 +516,20 @@ end # Get current image current_triq="TrIQ_$(text_nmass).bmp" msgtriq="TrIQ image with the Nmass of $(replace(text_nmass, "_" => "."))" - # Create colorbar - ticks=round.(range(0, (stop=maximum(sliceTriq)*triqProb), length=15), sigdigits=3) - Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(sliceTriq)*triqProb),ticks=ticks, label="Intensity", size = 25) + # Create colorbar + #ticks=round.(range(0, (stop=maximum(slice)*triqProb), length=10), sigdigits=3) + ticks=range(0, (stop=maximum(slice)*triqProb), length=5) + + """ + function log_tick_formatter(values) + return map(v -> "10" * Makie.UnicodeFun.to_superscript(round(Int64, v)), values) + end + """ + + println("ticks: $(typeof(ticks))") + #Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)*triqProb),ticks=ticks,tickformat=log_tick_formatter, label="Intensity", size = 25) + Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)*triqProb),ticks=ticks, label="Intensity", size = 25) + println("Colorbar: $(typeof(fig))") save("public/colorbar_TrIQ_$(text_nmass).png", fig) colorbarT="/colorbar_TrIQ_$(text_nmass).png?t=$(timestamp)" # Get current colorbar @@ -534,7 +547,7 @@ end else # If we don't use TrIQ image_path=joinpath("./public", "MSI_$(text_nmass).bmp") ##sliceQuant=IntQuant(slice) - sliceQuant=IntQuantCl(slice,colorLevel) + sliceQuant=IntQuantCl(slice,Int(colorLevel-1)) #println("slice raw: $(typeof(slice))") #println("slice in intQuant: $(typeof(sliceQuant))") sliceQuant=reverse(sliceQuant, dims=2) @@ -548,8 +561,8 @@ end msgimg="Image with the Nmass of $(replace(text_nmass, "_" => "."))" # Create colorbar #ticks=round.(range(0, stop=maximum(slice), length=10), sigdigits=3) - ticks=round.(range(0, stop=maximum(sliceQuant), length=15), sigdigits=3) - Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(sliceQuant)),ticks=ticks, label="Intensity", size = 25) + ticks=range(0, stop=maximum(slice), length=5) + Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)),ticks=ticks, label="Intensity", size = 25) save("public/colorbar_MSI_$(text_nmass).png", fig) colorbar="/colorbar_MSI_$(text_nmass).png?t=$(timestamp)" # Get current colorbar diff --git a/app.jl.html b/app.jl.html index 3d2b22d..256c7f3 100644 --- a/app.jl.html +++ b/app.jl.html @@ -60,18 +60,16 @@
+ :rules="[ val => !!val || '* Required', val => val >= 0.0 || 'Need positive mass values']">
- + :rules="[val => !!val || '* Required', val => val >= 0.0 && val <= 1.0 || 'Needs to be in range between 0 and 1']">
+ label="Color level" type="number" :rules="[ val => !!val || '* Required', val => val >= 2 && val <= 256 || 'Needs to be in range between 2 and 256']">
diff --git a/julia_imzML_visual.jl b/julia_imzML_visual.jl index a4d5fdb..e71d5b0 100644 --- a/julia_imzML_visual.jl +++ b/julia_imzML_visual.jl @@ -15,14 +15,16 @@ end # SaveBitmap is also originally a function of the mzML imzML library in julia, # This function dinamically adjust the color palete adjusting to the ammount of colors # available in pixmap -function SaveBitmapCl( name, - pixMap::Array{UInt8,2}, - colorTable::Array{UInt32,1} ) +function SaveBitmapCl( name, pixMap::Array{UInt8,2}, colorTable::Array{UInt32,1} ) # Get image dimensions dim = size( pixMap ) if length( dim ) != 2 return 0 end + # Normalize pixel values to get a more accurate reading of the image + min_val = minimum(pixMap) + max_val = maximum(pixMap) + pixMap = round.(UInt8, 255 * (pixMap .- min_val) ./ (max_val - min_val)) # Compute row padding padding = ( 4 - dim[1] & 0x3 ) & 0x3 # Compute file dimensions. Header = 14 + 40 + ( 256 * 4 ) = 1078 @@ -36,17 +38,12 @@ function SaveBitmapCl( name, # Save info header write( stream, UInt32[ 40, dim[1], dim[2], 0x80001, 0 ] ) write( stream, UInt32[ imgBytes, 0, 0, 256, 0 ] ) - # Get unique colors displayed in pixMap - unique_colors = unique(vec(pixMap)) - n_colors = length(unique_colors) - # Color levels can't surpass 256 - levels = min(n_colors, 256) - extendedColorTable = zeros(UInt32, 256) - for i in 1:256 - idx = ceil(Int, i * levels / 256) - extendedColorTable[i] = colorTable[idx] + # Save color table + write( stream, colorTable ) + if length( colorTable ) < 256 + fixTable = zeros( UInt32, 256 - length( colorTable ) ) + write( stream, fixTable ) end - write(stream, extendedColorTable) # Save image pixels if padding == 0 for i = 1:dim[2] diff --git a/start_MSI_GUI.jl b/start_MSI_GUI.jl index 35cd8ee..973cbd6 100644 --- a/start_MSI_GUI.jl +++ b/start_MSI_GUI.jl @@ -1,4 +1,5 @@ using Pkg +sTime=time() Pkg.activate(".") Pkg.instantiate() Pkg.gc() @@ -31,6 +32,8 @@ Genie.loadapp() # Start the Genie server @async begin up(host="127.0.0.1", port=1481) + eTime=round(time()-sTime,digits=3) + println("Julia MSI GUI took $(eTime) seconds booting") url = "http://127.0.0.1:1481" # Open the URL in the default web browser based on the OS if Sys.isapple() @@ -43,5 +46,4 @@ Genie.loadapp() @async run(`Start-Process $url`) # For Windows end end - wait() \ No newline at end of file From 11349330a4de4c6cb8d2ac93c4339ab7636dd57a Mon Sep 17 00:00:00 2001 From: Pixelguy14 Date: Thu, 30 Jan 2025 18:17:32 -0600 Subject: [PATCH 3/3] colorbar scale for both with triq filter and without is finished --- app.jl | 72 +++++++++++++++++++++++++++++++------------ julia_imzML_visual.jl | 29 ++++++++++++++--- 2 files changed, 77 insertions(+), 24 deletions(-) diff --git a/app.jl b/app.jl index 73dd73f..190fac0 100644 --- a/app.jl +++ b/app.jl @@ -13,7 +13,6 @@ using Images using LinearAlgebra using NativeFileDialog # Opens the file explorer depending on the OS using StipplePlotly -using Printf include("./julia_imzML_visual.jl") @genietools @@ -123,7 +122,7 @@ function loadContourPlot(interfaceImg::String) img_gray=Gray.(img) img_array=Array(img_gray) # parse matrix to int32 to closely resemble similarity to original bitmap - elevation=int32.(Array(img_gray)) + elevation=Float32.(Array(img_array))./ 255.0 # Normalize between 0 and 1 # Smooth the image sigma=3.0 @@ -174,7 +173,7 @@ function loadSurfacePlot(interfaceImg::String) 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 + elevation=Float32.(Array(img_array)) ./ 255.0 # Normalize between 0 and 1 #println("Elevation size:", size(elevation)) # Smooth the image sigma=3.0 @@ -248,6 +247,40 @@ function crossLinesPlot(x, y, maxwidth, maxheight) return trace1, trace2 end +function log_tick_formatter(values::Vector{Float64}) + #println("values: $(values) + type: $(typeof(values))") + # Initialize exponents dictionary + exponents=zeros(Int, length(values)) + formValues=zeros(Float64, length(values)) + for i in 1:length(values) + value = values[i] + #println("value: $(value)") + if value >= 1000 # positive formatting for notation + while value >= 1000 + value /= 10 + exponents[i] += 1 + end + #println("value: $(value) x10^$(exponents[i])") + elseif value > 0 && value < 1 # negative formatting for notation + while value < 1 + value *= 10 + exponents[i] -= 1 + end + #values[i] = round(values[i], digits=2) + #println("value: $(value) x10^$(exponents[i])") + end + #formatted_values[i] = values[i] != 0 ? "$(round(values[i], digits=2))x10" * Makie.UnicodeFun.to_superscript(exponents[i]) : "0" + formValues[i]=value + end + #return formatted_values + #return map(v -> values * "x10" * Makie.UnicodeFun.to_superscript(round(Int64, v)), exponents) + #println("formated values: $(formValues) + type: $(typeof(formValues))") + #println("exponents: $(exponents) + type: $(typeof(exponents))") + #return map((v, e) -> "$(round(v, digits=2))x10" * Makie.UnicodeFun.to_superscript(e), formValues, exponents) + return map((v, e) -> e == 0 ? "$(round(v, sigdigits=2))" : "$(round(v, sigdigits=2))x10" * Makie.UnicodeFun.to_superscript(e), formValues, exponents) + +end + # == Reactive code == # Reactive code to make the UI interactive @app begin @@ -494,8 +527,9 @@ end 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=(128, 256)) # Container + #slice=GetSlice(spectra, Nmass, Tol) + slice=GetMzSliceJl(spectra,Nmass,Tol) + fig=CairoMakie.Figure(size=(150, 250)) # Container # Append a query string to force the image to refresh timestamp=string(time_ns()) if triqEnabled # If we have TrIQ @@ -517,19 +551,17 @@ end current_triq="TrIQ_$(text_nmass).bmp" msgtriq="TrIQ image with the Nmass of $(replace(text_nmass, "_" => "."))" # Create colorbar + bound = julia_mzML_imzML.GetOutlierThres(slice, triqProb) + levels = range(bound[1],stop=bound[2], length=8) + #println("range of the levels 1: $(levels)") + levels = vcat(levels, 2*levels[end]-levels[end-1]) + #println("range of the levels 2: $(levels) + $(length(levels))") #ticks=round.(range(0, (stop=maximum(slice)*triqProb), length=10), sigdigits=3) - ticks=range(0, (stop=maximum(slice)*triqProb), length=5) - - """ - function log_tick_formatter(values) - return map(v -> "10" * Makie.UnicodeFun.to_superscript(round(Int64, v)), values) - end - """ - - println("ticks: $(typeof(ticks))") - #Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)*triqProb),ticks=ticks,tickformat=log_tick_formatter, label="Intensity", size = 25) - Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)*triqProb),ticks=ticks, label="Intensity", size = 25) - println("Colorbar: $(typeof(fig))") + #ticks=range(0, (stop=maximum(slice)*triqProb), length=5) + #println("ticks: $(typeof(ticks))") + Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, bound[2]),ticks=levels,tickformat=log_tick_formatter, label="Intensity", size = 25) + #Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)*triqProb),ticks=ticks, label="Intensity", size = 25) + #println("Colorbar: $(typeof(fig))") save("public/colorbar_TrIQ_$(text_nmass).png", fig) colorbarT="/colorbar_TrIQ_$(text_nmass).png?t=$(timestamp)" # Get current colorbar @@ -560,9 +592,11 @@ end current_msi="MSI_$(text_nmass).bmp" msgimg="Image with the Nmass of $(replace(text_nmass, "_" => "."))" # Create colorbar + levels=range(0,maximum(slice),length=8) #ticks=round.(range(0, stop=maximum(slice), length=10), sigdigits=3) - ticks=range(0, stop=maximum(slice), length=5) - Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)),ticks=ticks, label="Intensity", size = 25) + #ticks=range(0, stop=maximum(slice), length=5) + #Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)),ticks=ticks, label="Intensity", size = 25) + Colorbar(fig[1, 1], colormap=cgrad(:viridis, colorLevel, categorical=true), limits=(0, maximum(slice)),ticks=levels,tickformat=log_tick_formatter, label="Intensity", size = 25) save("public/colorbar_MSI_$(text_nmass).png", fig) colorbar="/colorbar_MSI_$(text_nmass).png?t=$(timestamp)" # Get current colorbar diff --git a/julia_imzML_visual.jl b/julia_imzML_visual.jl index e71d5b0..7be02f1 100644 --- a/julia_imzML_visual.jl +++ b/julia_imzML_visual.jl @@ -12,7 +12,7 @@ function IntQuantCl( slice , colorLevel) return image end -# SaveBitmap is also originally a function of the mzML imzML library in julia, +# SaveBitmap originally a function of the mzML imzML library in julia, # This function dinamically adjust the color palete adjusting to the ammount of colors # available in pixmap function SaveBitmapCl( name, pixMap::Array{UInt8,2}, colorTable::Array{UInt32,1} ) @@ -22,9 +22,9 @@ function SaveBitmapCl( name, pixMap::Array{UInt8,2}, colorTable::Array{UInt32,1} return 0 end # Normalize pixel values to get a more accurate reading of the image - min_val = minimum(pixMap) - max_val = maximum(pixMap) - pixMap = round.(UInt8, 255 * (pixMap .- min_val) ./ (max_val - min_val)) + minVal = minimum(pixMap) + maxVal = maximum(pixMap) + pixMap = round.(UInt8, 255 * (pixMap .- minVal) ./ (maxVal - minVal)) # Compute row padding padding = ( 4 - dim[1] & 0x3 ) & 0x3 # Compute file dimensions. Header = 14 + 40 + ( 256 * 4 ) = 1078 @@ -58,4 +58,23 @@ function SaveBitmapCl( name, pixMap::Array{UInt8,2}, colorTable::Array{UInt32,1} end # Close file close( stream ) -end \ No newline at end of file +end + +# SaveBitmap originally a function of the mzML imzML library in julia, +# now has an adjustment for NaN values in case they exist to mantain data integrity +function GetMzSliceJl(imzML, mass, tolerance) + # Alloc space for slice + width = maximum(imzML[1, :]) + height = maximum(imzML[2, :]) + image = fill(0.0, width, height) + + for i in 1:size(imzML)[2] + index = julia_mzML_imzML.FindMass(imzML[3, i], mass, tolerance) + if index != 0 + image[imzML[1, i], imzML[2, i]] = imzML[4, i][index] + end + end + # Adjustment for NaN values with 0 + replace!(image, NaN => 0.0) + return image +end