diff --git a/docs/make.jl b/docs/make.jl index b8dd074..7fe9f45 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -3,17 +3,18 @@ ENV["GKSwstype"] = "100" ENV["LINES"] = "9" ENV["COLUMNS"] = "60" using Documenter, ScatteringTransform, ScatteringPlots +mkpath("docs/src/figures") makedocs( sitename = "ScatteringTransform.jl", format = Documenter.HTML(), + modules = [ScatteringTransform, ScatteringPlots], authors="David Weber, Naoki Saito", clean=true, + checkdocs = :exports, # This ignores the ContinuousWavelets warnings during doctests doctestfilters = [ - r"┌ Warning:.*", - r"│.*", - r"└ @ ContinuousWavelets.*" + r"┌ Warning:.*\n│.*\n└ @ ContinuousWavelets.*\n?"s, ], pages = Any[ "Home" => "index.md", @@ -27,7 +28,7 @@ makedocs( ], ], # <--- This bracket closes the 'pages' list! - warnonly = [:cross_references], # <--- Now this is a separate argument + warnonly = [:cross_references, :missing_docs], # <--- Now this is a separate argument ) deploydocs(; diff --git a/docs/src/figures/firstLayer.png b/docs/src/figures/firstLayer.png new file mode 100644 index 0000000..7e438b0 Binary files /dev/null and b/docs/src/figures/firstLayer.png differ diff --git a/docs/src/figures/firstLayerAll.png b/docs/src/figures/firstLayerAll.png new file mode 100644 index 0000000..3391369 Binary files /dev/null and b/docs/src/figures/firstLayerAll.png differ diff --git a/docs/src/figures/sliceByFirst.gif b/docs/src/figures/sliceByFirst.gif new file mode 100644 index 0000000..a18bd48 Binary files /dev/null and b/docs/src/figures/sliceByFirst.gif differ diff --git a/docs/src/figures/sliceBySecond.gif b/docs/src/figures/sliceBySecond.gif new file mode 100644 index 0000000..4fdc4f8 Binary files /dev/null and b/docs/src/figures/sliceBySecond.gif differ diff --git a/docs/src/index.md b/docs/src/index.md index 37f33a4..0692850 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -25,10 +25,10 @@ using Wavelets, Plots N = 2047 f = testfunction(N, "Doppler") plot(f, legend=false, title="Doppler signal") -savefig("rawDoppler.svg"); #hide +savefig("figures/rawDoppler.svg"); #hide ``` -![](rawDoppler.svg) +![](figures/rawDoppler.svg) First we need to make a `scatteringTransform` instance, which will create and store all of the necessary filters, subsampling operators, nonlinear functions, etc. The parameters are described in the `scatteringTransform` type. @@ -55,40 +55,50 @@ plot(sf[0][:, 1, 1], title="Zeroth Layer", legend=false) The first layer is the average of the absolute value of the scalogram: ```@example ex -f1, f2, f3 = getMeanFreq(St) # the mean frequencies for the wavelets in each layer -heatmap(1:size(sf[1], 1), f1[1:end-1], sf[1][:, :, 1]', xlabel="time index", ylabel="Frequency (Hz)", color=:viridis, title="First Layer") +plotFirstLayer(sf, St, "figures/firstLayer.png") +nothing # hide ``` +![](figures/firstLayer.png) + +With the plotting utilities included in this package, you are able to display the previous plot along with the original signal and the first layer wavelet gradients: + +```@example ex +plotFirstLayer1DAll(sf, f, "figures/firstLayerAll.png") +nothing # hide +``` +![](figures/firstLayerAll.png) + ### Second Layer The second layer is where the scattering transform begins to get more involved, and reflects both the frequency of [the envelope](https://en.wikipedia.org/wiki/Analytic_signal#Instantaneous_amplitude_and_phase) surrounding the signal and the frequency of the signal itself. -Visualizing this is also somewhat difficult, since each path in the second layer is indexed by a pair `(s2,s1)`, where `s2` is the frequency used for the second layer wavelet, and `s1` is the frequency used for the first layer wavelet. +With our plotting utilities, you can display the second layer with respect to specified wavelet paths from the first and second layer. After specifying the `sf` and `St` for your plot, provide an array of the desired wavelets from the first layer and an array of the desired wavelets from the second layer. To this end, lets make two gifs, the first with the _first_ layer frequency varying with time: ```@example ex -anim = Animation() -for jj = 1:length(f1)-1 - toPlot = dropdims(sf[pathLocs(2, (:, jj))], dims=3) - heatmap(1:size(sf[2], 1), f2[1:end-1], toPlot', title="index=$(jj), first layer frequency=$(round(f1[jj],sigdigits=4))Hz", xlabel="time", ylabel="Frequency (Hz)", c=cgrad(:viridis, scale=:exp)) - frame(anim) -end -gif(anim, "sliceByFirst.gif", fps=1) +plotSecondLayerFixAndVary(sf, St, 1:30, 1, "figures/sliceByFirst.gif", 1) +nothing # hide ``` +![](figures/sliceByFirst.gif) By fixing the first layer frequency, we get the scalogram of a single line from the scalogram above. -As the first layer frequency increases, the energy concentrates to the beginning of the signal and increased frequency, and generally decreases. +As the first layer frequency increases, the energy concentrates to the beginning of the signal while the signal strength generally decreases. The second has the _second_ layer frequency varying with time: ```@example ex -anim = Animation() -for jj = 1:length(f2)-1 - toPlot = dropdims(sf[pathLocs(2, (jj, :))], dims=3) - heatmap(1:size(sf[2], 1), f1[1:end-1], toPlot', title="index=$(jj), second layer frequency=$(round(f2[jj],sigdigits=4))Hz", c=cgrad(:viridis, scale=:exp)) - frame(anim) -end -gif(anim, "sliceBySecond.gif", fps=1) +plotSecondLayerFixAndVary(sf, St, 1, 1:28, "figures/sliceBySecond.gif", 1) +nothing # hide +``` +![](figures/sliceBySecond.gif) + +If desired, this package allows one to plot the results of a specific path. Here is an example, where we are plotting the resulting plot if we were to use first layer wavelet 3 and second layer wavelet 1. + +```@example ex +plotSecondLayerSpecificPath(sf, St, 3, 1, f) +savefig("figures/specificPath.png"); #hide ``` +![](figures/specificPath.png) For any fixed second layer frequency, we get approximately the curve in the first layer scalogram, with different portions emphasized, and the overall mass decreasing as the frequency increases, corresponding to the decreasing amplitude of the envelope for the doppler signal. These plots can also be created using various plotting utilities defined in this package. @@ -97,9 +107,21 @@ For example, we can generate a denser representation with the `plotSecondLayer` ```@example ex plotSecondLayer(sf, St) -savefig("second.png") #hide +savefig("figures/secondLayer.png"); #hide ``` -![](second.png) +![](figures/secondLayer.png) where the frequencies are along the axes, the heatmap gives the largest value across time for that path, and at each path is a small plot of the averaged timecourse. + + +### Joint Plot + +Finally, we can constuct a joint plot of much of our prior information. This plot will display the zeroth layer, first layer and second layer information for a given example. + +```@example ex +jointPlot(sf, "Scattering Transform", :viridis, St) +savefig("figures/jointPlot.png"); #hide +``` + +![](figures/jointPlot.png) diff --git a/docs/src/plots.md b/docs/src/plots.md index 7e40218..c4080fb 100644 --- a/docs/src/plots.md +++ b/docs/src/plots.md @@ -1,5 +1,7 @@ # Plotting Scattering Transforms ```@autodocs -Modules = [ScatteringPlots] +Modules = [ScatteringTransform, ScatteringPlots] +Pages = ["scatteringplots.jl"] +Order = [:function] ``` diff --git a/src/ScatteringTransform.jl b/src/ScatteringTransform.jl index efa1c5a..9d81a01 100644 --- a/src/ScatteringTransform.jl +++ b/src/ScatteringTransform.jl @@ -46,5 +46,5 @@ export getWavelets, flatten, roll, importantCoords, batchOff, getParameters, get export roll, wrap, flatten include("adjoints.jl") include("scatteringplots.jl") -export jointPlot, plotFirstLayer1D, gifFirstLayer, plotSecondLayer, plotSecondLayer1D +export jointPlot, plotFirstLayer1D, gifFirstLayer, plotFirstLayer1DAll, plotFirstLayer, plotSecondLayer, plotSecondLayer1D, plotSecondLayerSpecificPath, plotSecondLayer1DSubsetGif, plotSecondLayerFixAndVary end # end Module diff --git a/src/scatteringplots.jl b/src/scatteringplots.jl index 3650448..9bed67a 100644 --- a/src/scatteringplots.jl +++ b/src/scatteringplots.jl @@ -1,34 +1,78 @@ """ - plotFirstLayer1D(j,origLoc,cline=:darkrainbow) -""" -function plotFirstLayer1D(j, origLoc, original, cline=:darkrainbow) - - space = plot(origLoc[1][:, :, j], line_z=(1:size(origLoc[1], 2))', - legend=false, colorbar=true, color=cline, - title="first layer gradient wavelet $j varying location") - org = plot([original original], line_z=([-20; 1:size(origLoc[1], 2)...])', legend=false, colorbar=true, color=cline) # todo: including the colorbar here is a real hack to get them to line up - ∇h = heatmap(origLoc[1][:, 1:end, j]', xlabel="space", - ylabel="wavelet location", title="First layer gradient j=$j") - ∇̂h = heatmap(log.(abs.(rfft(origLoc[1][:, 1:end, j], 1)) .^ 2)', xlabel="frequency", - ylabel="wavelet location", title="Log Power Frequency domain j=$j") + plotFirstLayer1D(j, origLoc, origSig, index) +Function that plots the first layer gradient wavelet at index `j` across space, along with the original signal. +It also includes heatmaps of the gradient wavelet in both the spatial and frequency domains. +The variable `j` specifies which wavelet to plot from the first layer, `index` specifies which example in the batch to plot, +`origLoc` is the `ScatteredOut` object containing the scattering transform results, and `origSig` is the original input signal. +""" +function plotFirstLayer1D(j, origLoc, origSig, index=1) + space = plot(origLoc[1][:, j, index], xlim=(0, length(origLoc[1][:, j, index])+1), legend=false, + color=:red, title="First Layer - Gradient Wavelet $j - Varying Location") + org = plot(origSig[:,:,index], legend=false, color=:red, title="Original Signal", xlim=(0, length(origSig[:,:,index])+1)) + ∇h = heatmap(origLoc[1][:, j, index]', xlabel="space", + yticks=false, ylabel="", title="First Layer gradient - Wavelet j=$j") + ∇̂h = heatmap(log.(abs.(rfft(origLoc[1][:, j, index], 1)) .^ 2)', xlabel="frequency", + yticks=false, ylabel="", title="Log-power Frequency Domain - Wavelet j=$j") l = Plots.@layout [a; b{0.1h}; [b c]] - plot(space, org, ∇h, ∇̂h, layout=l) + plot(space, org, ∇h, ∇̂h, layout=l, size=(1200, 800), margin=5Plots.mm) end """ - gifFirstLayer(origLoc, saveTo="tmp.gif", fps = 2) + gifFirstLayer(origLoc, origSig, saveTo="tmp.gif", fps = 2, index) +Function to create a GIF visualizing all wavelets in the first layer across space for each example in the batch. +The variable `origLoc` is the `ScatteredOut` object containing the scattering transform results, `index` specifies which example in the batch to plot, +`origSig` is the original input signal, `saveTo` specifies the file path to save the GIF, and `fps` sets the frames per second for the GIF animation. """ -function gifFirstLayer(origLoc, firstSig, saveTo="gradientFigures/tmp.gif", fps=2) +function gifFirstLayer(origLoc, origSig, saveTo="gradientFigures/tmp.gif", fps=2, index=1) anim = Animation() - for j = 1:size(origLoc[1])[end] - plotFirstLayer1D(j, origLoc, firstSig) + for j = 1:size(origLoc[1])[end-1] + plotFirstLayer1D(j, origLoc, origSig, index) frame(anim) end gif(anim, saveTo, fps=fps) end +""" + plotFirstLayer1DAll(origLoc, origSig, saveTo="gradientFigures/tmp2.png", index=1, cline=:darkrainbow) +Function that plots all first layer gradient wavelets for a specific example signal `index` across space, along with the original signal. +It also includes heatmaps of the gradient wavelets in both the spatial and frequency domains. +The variable `index` specifies which example in the batch to plot, `origLoc` is the `ScatteredOut` object +containing the scattering transform results, `origSig` is the original input signal, and `saveTo` is the file path to save the plot. +""" +function plotFirstLayer1DAll(origLoc, origSig, saveTo="gradientFigures/tmp2.png", index=1, cline=:darkrainbow) + space = plot(origLoc[1][:, :, index], line_z=(1:size(origLoc[1], 2))', xlim=(0, length(origLoc[1][:, 1, index])+1), + legend=false, colorbar=true, color=cline, title="first layer gradient wavelets") + org = plot(origSig[:,:,index], legend=false, color=:red, title="Original Signal", xlim=(0, length(origSig[:,:,index])+1)) + ∇h = heatmap(origLoc[1][:, 1:end, index]', xlabel="space", + ylabel="wavelet index", title="First Layer gradients") + ∇̂h = heatmap(log.(abs.(rfft(origLoc[1][:, 1:end, index], 1)) .^ 2)', xlabel="frequency", + ylabel="wavelet index", title="Log-power Frequency Domain") + l = Plots.@layout [a; b{0.1h}; [b c]] + plt = plot(space, org, ∇h, ∇̂h, layout=l, size=(1200, 800), margin=5Plots.mm) + savefig(plt, saveTo) +end + +""" + plotFirstLayer(stw, St, saveTo="gradientFigures/firstLayer.png", index=1) +Function that creates a heatmap of the first layer scattering transform results at a specified example index. +The variable `stw` is the scattered output, `St` is the scattering transform object, `saveTo` is the file +path to save the plot, and `index` specifies which example in the batch to plot. +""" +function plotFirstLayer(stw, St, saveTo="gradientFigures/firstLayer.png", index=1) + f1, f2, f3 = getMeanFreq(St) # the mean frequencies for the wavelets in each layer. + plt = heatmap(1:size(stw[1], 1), f1[1:end-1], stw[1][:, :, index]', + xlabel="time index", ylabel="Frequency (Hz)", + color=:viridis, title="First Layer", size=(1200, 800)) + savefig(plt, saveTo) +end + + meanWave(wave) = sum(real.(range(0, stop=1, length=size(wave, 1)) .* wave), dims=1) ./ sum(real.(wave), dims=1) +# As far as I can tell, this function is not used elsewhere. +""" + plotSecondLayer1D(loc, origLoc, wave1, wave2, original=false, subsamSz=(128,85,)) +""" function plotSecondLayer1D(loc, origLoc, wave1, wave2, original=false, subsamSz=(128, 85,), c=:thermal, lastDiagFreq=true) waveUsed = real.(ifftshift(irfft(wave1[:, loc[2]], subsamSz[1] * 2))) l1wave = plot(waveUsed, legend=false, titlefontsize=8, title="layer 1 ($(loc[2]))") @@ -58,7 +102,89 @@ function plotSecondLayer1D(loc, origLoc, wave1, wave2, original=false, subsamSz= end """ - plotSecondLayer(stw; title="Second Layer results", xVals=-1, yVals=-1, logPower=true, toHeat=nothing, c=cgrad(:viridis, [0,.9]), threshold=0, linePalette=:greys, minLog=NaN, kwargs...) + plotSecondLayerSpecificPath(stw, St, firstLayerWaveletIndex, secondLayerWaveletIndex, original, index=1) +`stw` is the scattered output, `St` is the scattering transform object, `firstLayerWaveletIndex` and `secondLayerWaveletIndex` specify the path to plot, `original` is the original signal, and `index` specifies +which example in the batch to plot. This function creates a plot showing the original signal and the scattering result for the specified path. It also displays the mean frequencies associated with the +selected wavelets. Finally, it displays the log-power norm of the second layer signal for the specified path. This value is used elsewhere to create heatmaps of the second layer scattering results. +""" +function plotSecondLayerSpecificPath(stw, St, firstLayerWaveletIndex, secondLayerWaveletIndex, original, index=1) + # Plot of original signal. + org = plot(original[:,:,index], legend=false, color=:red, title="Original Signal", xlabel="time (samples)", ylabel="amplitude", xlims=(0, length(original[:,:,index])+1)) + f1, f2, f3 = getMeanFreq(St) + + # Plot the signal for a specific path. + signalLayer1Freq = f1[firstLayerWaveletIndex]; signalLayer2Freq = f2[secondLayerWaveletIndex] + titlePlot = plot(title="Path: First Layer - wavelet $firstLayerWaveletIndex, Second Layer - wavelet $secondLayerWaveletIndex\n" * + "First Layer Freq = $(round(signalLayer1Freq, sigdigits=3)) Hz | " * + "Second Layer Freq = $(round(signalLayer2Freq, sigdigits=3)) Hz", + grid=false, showaxis=false, xticks=nothing, yticks=nothing, bottom_margin=-5Plots.px, titlefontsize=11) + + path_spatial = stw[2][:, secondLayerWaveletIndex, firstLayerWaveletIndex, index] + ∇h = plot(path_spatial, xlabel="time (samples)", ylabel="amplitude", title="Second Layer Plot", legend=false, linewidth=1.5, frame=:box, fill=0, fillalpha=0.5, + xlims=(0, length(path_spatial)), ylims=(0, maximum(path_spatial)*1.01)) + + secondLayerNorm = log10.(norm(stw[2][:, secondLayerWaveletIndex, firstLayerWaveletIndex, index])) + normPlot = plot(title="Second Layer Signal norm (log-power) = $(round(secondLayerNorm, sigdigits=4))", + grid=false, showaxis=false, xticks=nothing, yticks=nothing, titlefontsize=11, framestyle=:none) + l = Plots.@layout [a{0.4h}; title{0.05h}; c; d{0.05h}] + plot(org, titlePlot, ∇h, normPlot, layout=l, margin=4Plots.mm, size=(900,600)) +end + +""" + plotSecondLayer1DSubsetGif(stw, St, firstLayerWavelets, secondLayerWavelets, original, saveTo="secondLayerFigures/tmp2.gif", fps=2, index=1) +Create a GIF visualizing the second layer scattering results for specified subsets of wavelets from the first and second layers. The variables `firstLayerWavelets` and `secondLayerWavelets` are arrays +containing the indices of the wavelets to be visualized from the first and second layers, respectively. For example, to visualize all the wavelets from the first layer with respect to a specific +wavelet from the second layer, you can set `firstLayerWavelets = 1:size(stw[1], 2)` and `secondLayerWavelets = k`, where `k` is the index of the desired second layer wavelet. Once again, the `index` +parameter specifies which example in the batch to plot. It defaults to the first example in the batch. +""" +function plotSecondLayer1DSubsetGif(stw, St, firstLayerWavelets, secondLayerWavelets, original, saveTo="secondLayerFigures/tmp2.gif", fps=2, index=1) + anim = Animation() + for j in firstLayerWavelets, k in secondLayerWavelets + plotSecondLayerSpecificPath(stw, St, j, k, original, index) + frame(anim) + end + gif(anim, saveTo, fps=fps) +end + +""" + plotSecondLayerFixAndVary(stw, St, firstLayerWavelets, secondLayerWavelets, saveTo="secondLayerFigures/sliceByLayer.gif", fps=2, index=1) +Create a GIF visualizing slices of the second layer scattering results by fixing one layer's wavelet and varying the other layer's wavelet. +The variables `firstLayerWavelets` and `secondLayerWavelets` are arrays containing the indices of the wavelets to be visualized from the first and second layers, respectively. +If `firstLayerWavelets` contains only one index, the function fixes that wavelet and varies the second layer wavelets, and vice versa. +""" +function plotSecondLayerFixAndVary(stw, St, firstLayerWavelets, secondLayerWavelets, saveTo="secondLayerFigures/sliceByLayer.gif", fps=2, index=1) + f1, f2, f3 = getMeanFreq(St) + anim = Animation() + + if length(firstLayerWavelets) == 1 + # Fixed first layer, vary second layer. + fixedFirstIdx = firstLayerWavelets[1] + for jj in secondLayerWavelets + if jj > size(stw[2], 2) + continue + end + toPlot = stw[2][:, jj, :, index] + heatmap(1:size(toPlot, 1), f1[1:end-1], toPlot', title="Second Layer Wavelet $jj, Frequency=$(round(f2[jj],sigdigits=4))Hz", + xlabel="time (samples)", ylabel="First Layer Frequency (Hz)", c=cgrad(:viridis, scale=:exp)) + frame(anim) + end + else + # Fixed second layer, vary first layer. + for jj in firstLayerWavelets + if jj > size(stw[2], 3) + continue + end + toPlot = stw[2][:, :, jj, index] + heatmap(1:size(toPlot, 1), f2[1:end-1], toPlot', title="First Layer Wavelet $jj, Frequency=$(round(f1[jj],sigdigits=4))Hz", + xlabel="time (samples)", ylabel="Second Layer Frequency (Hz)", c=cgrad(:viridis, scale=:exp)) + frame(anim) + end + end + gif(anim, saveTo, fps=fps) +end + +""" + plotSecondLayer(stw, St, index=1; title="Second Layer results", xVals=-1, yVals=-1, logPower=true, toHeat=nothing, c=cgrad(:viridis, [0,.9]), threshold=0, linePalette=:greys, minLog=NaN, kwargs...) TODO fix the similarity of these names. xVals and yVals give the spacing of the grid, as it doesn't seem to be done correctly by default. xVals gives the distance from the left and the right @@ -67,18 +193,18 @@ also as a tuple. Default values are `xVals = (.037, .852), yVals = (.056, .939)` If you have no colorbar, set `xVals = (.0015, .997), yVals = (.002, .992)` In the case that arbitrary space has been introduced, if you have a title, use `xVals = (.037, .852), yVals = (.056, .939)`, or if you have no title, use `xVals = (.0105, .882), yVals = (.056, .939)` """ -function plotSecondLayer(stw::ScatteredOut, st; kwargs...) +function plotSecondLayer(stw::ScatteredOut, St, index=1; kwargs...) secondLayerRes = stw[2] if ndims(secondLayerRes) > 3 - return plotSecondLayer(secondLayerRes[:, :, :, 1], st; kwargs...) + return plotSecondLayer(secondLayerRes[:, :, :, index], St; kwargs...) else - return plotSecondLayer(secondLayerRes, st; kwargs...) + return plotSecondLayer(secondLayerRes, St; kwargs...) end end -function plotSecondLayer(stw, st; title="Second Layer results", xVals=-1, yVals=-1, logPower=true, toHeat=nothing, c=cgrad(:viridis, [0, 0.9]), threshold=0, freqsigdigits=3, linePalette=:greys, minLog=NaN, subClims=(Inf, -Inf), δt=1000, firstFreqSpacing=nothing, secondFreqSpacing=nothing, transp=true, labelRot=30, xlabel=nothing, ylabel=nothing, frameTypes=:box, miniFillAlpha=0.5, kwargs...) +function plotSecondLayer(stw, St; title="Second Layer results", xVals=-1, yVals=-1, logPower=true, toHeat=nothing, c=cgrad(:viridis, [0, 0.9]), threshold=0, freqsigdigits=3, linePalette=:greys, minLog=NaN, subClims=(Inf, -Inf), δt=1000, firstFreqSpacing=nothing, secondFreqSpacing=nothing, transp=true, labelRot=30, xlabel=nothing, ylabel=nothing, frameTypes=:box, miniFillAlpha=0.5, kwargs...) n, m = size(stw)[2:3] - freqs = getMeanFreq(st, δt) + freqs = getMeanFreq(St, δt) freqs = map(x -> round.(x, sigdigits=freqsigdigits), freqs)[1:2] gr(size=2.5 .* (280, 180)) if !(typeof(c) <: PlotUtils.ContinuousColorGradient) @@ -163,18 +289,24 @@ function plotSecondLayer(stw, st; title="Second Layer results", xVals=-1, yVals= plt end -function jointPlot(thingToPlot, thingName, cSymbol, St; sharedColorScaling=:exp, targetExample=1, δt=1000, freqigdigits=3, sharedColorbar=true, extraPlot=nothing, allPositive=false, logPower=false, kwargs...) +""" + jointPlot(thingToPlot, thingName, cSymbol, St; sharedColorScaling=:exp, targetExample=1, δt=1000, freqigdigits=3, sharedColorbar=false, extraPlot=nothing, allPositive=false, logPower=false) +Create a joint plot visualizing the zeroth, first, and second layer scattering results for a specified example. The variable `thingToPlot` is a tuple containing the scattering results for the +zeroth, first, and second layers, `thingName` is the title for the plot, `cSymbol` specifies the color gradient to use, and `St` is the scattering transform object. The function allows for +various customization options, including shared color scaling, target example selection, frequency digit rounding, and additional plotting options. +""" +function jointPlot(thingToPlot, thingName, cSymbol, St; sharedColorScaling=:exp, targetExample=1, δt=1000, freqigdigits=3, sharedColorbar=false, extraPlot=nothing, allPositive=false, logPower=false, kwargs...) if sharedColorbar clims = (min(minimum.(thingToPlot)...), max(maximum.(thingToPlot)...)) climszero = clims climsfirst = clims climssecond = clims - toHeat = [norm(thingToPlot[2][:, i, j, 1], Inf) for i = 1:size(thingToPlot[2], 2), j = 1:size(thingToPlot[2], 3)] + toHeat = [norm(thingToPlot[2][:, i, j, targetExample], Inf) for i = 1:size(thingToPlot[2], 2), j = 1:size(thingToPlot[2], 3)] else climszero = (min(minimum.(thingToPlot[0])...), max(maximum.(thingToPlot[0])...)) climsfirst = (min(minimum.(thingToPlot[1])...), max(maximum.(thingToPlot[1])...)) climssecond = (min(minimum.(thingToPlot[2])...), max(maximum.(thingToPlot[2])...)) - toHeat = [norm(thingToPlot[2][:, i, j, 1], Inf) for i = 1:size(thingToPlot[2], 2), j = 1:size(thingToPlot[2], 3)] + toHeat = [norm(thingToPlot[2][:, i, j, targetExample], Inf) for i = 1:size(thingToPlot[2], 2), j = 1:size(thingToPlot[2], 3)] end firstLay = thingToPlot[1][:, :, targetExample]' zeroLay = thingToPlot[0][:, :, targetExample]' @@ -219,5 +351,5 @@ function jointPlot(thingToPlot, thingName, cSymbol, St; sharedColorScaling=:exp, end titlePlot = plot(title=thingName, grid=false, showaxis=false, xticks=nothing, yticks=nothing, bottom_margin=-10Plots.px) lay = Plots.@layout [o{0.00001h}; [[a b; c{0.1h} d{0.1h}] b{0.04w}]] - plot(titlePlot, p2, p1, extraPlot, p0, colorbarOnly, layout=lay) + plot(titlePlot, p2, p1, extraPlot, p0, colorbarOnly, layout=lay, size=(1200,800)) end diff --git a/src/shared.jl b/src/shared.jl index 3b7f836..3ee8aaa 100644 --- a/src/shared.jl +++ b/src/shared.jl @@ -54,7 +54,7 @@ julia> varargs (:boundary => PerBoundary(), :frameBound => [1, 1], :normalization => (Inf, Inf)) julia> listVargs = ScatteringTransform.processArgs(3,varargs) -(Base.Pairs{Int64, Pair{Symbol}, Base.OneTo{Int64}, Tuple{Pair{Symbol, ContinuousWavelets.PerBoundary}, Pair{Symbol, Vector{Int64}}, Pair{Symbol, Tuple{Float64, Float64}}}}(1 => (:boundary => PerBoundary()), 2 => (:frameBound => [1, 1]), 3 => (:normalization => (Inf, Inf))), Base.Pairs{Int64, Pair{Symbol}, Base.OneTo{Int64}, Tuple{Pair{Symbol, ContinuousWavelets.PerBoundary}, Pair{Symbol, Vector{Int64}}, Pair{Symbol, Tuple{Float64, Float64}}}}(1 => (:boundary => PerBoundary()), 2 => (:frameBound => [1, 1]), 3 => (:normalization => (Inf, Inf))), Base.Pairs{Int64, Pair{Symbol}, Base.OneTo{Int64}, Tuple{Pair{Symbol, ContinuousWavelets.PerBoundary}, Pair{Symbol, Vector{Int64}}, Pair{Symbol, Tuple{Float64, Float64}}}}(1 => (:boundary => PerBoundary()), 2 => (:frameBound => [1, 1]), 3 => (:normalization => (Inf, Inf)))) +(Base.Pairs{Int64, Pair{Symbol}, Base.OneTo{Int64}, Tuple{Pair{Symbol, PerBoundary}, Pair{Symbol, Vector{Int64}}, Pair{Symbol, Tuple{Float64, Float64}}}}(1 => (:boundary => PerBoundary()), 2 => (:frameBound => [1, 1]), 3 => (:normalization => (Inf, Inf))), Base.Pairs{Int64, Pair{Symbol}, Base.OneTo{Int64}, Tuple{Pair{Symbol, PerBoundary}, Pair{Symbol, Vector{Int64}}, Pair{Symbol, Tuple{Float64, Float64}}}}(1 => (:boundary => PerBoundary()), 2 => (:frameBound => [1, 1]), 3 => (:normalization => (Inf, Inf))), Base.Pairs{Int64, Pair{Symbol}, Base.OneTo{Int64}, Tuple{Pair{Symbol, PerBoundary}, Pair{Symbol, Vector{Int64}}, Pair{Symbol, Tuple{Float64, Float64}}}}(1 => (:boundary => PerBoundary()), 2 => (:frameBound => [1, 1]), 3 => (:normalization => (Inf, Inf)))) julia> listVargs[1] pairs(::Tuple{Pair{Symbol, ContinuousWavelets.PerBoundary}, Pair{Symbol, Vector{Int64}}, Pair{Symbol, Tuple{Float64, Float64}}}) with 3 entries: diff --git a/src/transform.jl b/src/transform.jl index 81be42f..ee2d64b 100644 --- a/src/transform.jl +++ b/src/transform.jl @@ -62,15 +62,15 @@ julia> x = [ones(128); zeros(128)]; julia> St = stFlux((256,1,1)) ┌ Warning: there are wavelets whose peaks are far enough apart that the trough between them is less than half the height of the highest frequency wavelet -│ minimalRegionComparedToLastPeak = 2.45709167339886 -└ @ ContinuousWavelets ~/allHail/projects/ContinuousWavelets/src/sanityChecks.jl:28 +│ minimalRegionComparedToLastPeak = 7.0515 +└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/KeITS/src/sanityChecks.jl:33 ┌ Warning: there are wavelets whose peaks are far enough apart that the trough between them is less than half the height of the highest frequency wavelet -│ minimalRegionComparedToLastPeak = 2.5356674293941244 -└ @ ContinuousWavelets ~/allHail/projects/ContinuousWavelets/src/sanityChecks.jl:28 +│ minimalRegionComparedToLastPeak = 4.815 +└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/KeITS/src/sanityChecks.jl:33 ┌ Warning: there are wavelets whose peaks are far enough apart that the trough between them is less than half the height of the highest frequency wavelet -│ minimalRegionComparedToLastPeak = 2.2954419414285616 -└ @ ContinuousWavelets ~/allHail/projects/ContinuousWavelets/src/sanityChecks.jl:28 -stFlux{2, Nd=1, filters=[12], σ = abs, batchSize = 1, normalize = true} +│ minimalRegionComparedToLastPeak = 3.2091 +└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/KeITS/src/sanityChecks.jl:33 +stFlux{Nd=1, m=2, filters=[12, 11], σ = abs, batchSize = 1, normalize = true} julia> St(x) ScatteredOut{Array{Float32},3} 1 dim. OutputSizes: diff --git a/src/utilities.jl b/src/utilities.jl index 7c504cf..852d566 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -51,16 +51,25 @@ Get a list of the mean frequencies for the filter bank in each layer. The averag julia> using ScatteringTransform julia> St = scatteringTransform((1024,1,1),2) -stFlux{2, Nd=1, filters=[15], σ = abs, batchSize = 1, normalize = true} +┌ Warning: there are wavelets whose peaks are far enough apart that the trough between them is less than half the height of the highest frequency wavelet +│ minimalRegionComparedToLastPeak = 8.0292 +└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/KeITS/src/sanityChecks.jl:33 +┌ Warning: there are wavelets whose peaks are far enough apart that the trough between them is less than half the height of the highest frequency wavelet +│ minimalRegionComparedToLastPeak = 9.2355 +└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/KeITS/src/sanityChecks.jl:33 +┌ Warning: there are wavelets whose peaks are far enough apart that the trough between them is less than half the height of the highest frequency wavelet +│ minimalRegionComparedToLastPeak = 9.6864 +└ @ ContinuousWavelets ~/.julia/packages/ContinuousWavelets/KeITS/src/sanityChecks.jl:33 +stFlux{Nd=1, m=2, filters=[15, 14], σ = abs, batchSize = 1, normalize = true} julia> f1, f2, f3 = getMeanFreq(St); julia> f1' 1×16 adjoint(::Vector{Float64}) with eltype Float64: - 7.70368 54.4302 78.7967 … 315.712 338.416 18.6697 + 7.70368 54.4302 78.7967 … 315.712 338.416 6.36036 julia> f2' 1×15 adjoint(::Vector{Float64}) with eltype Float64: - 10.8253 64.1205 89.7788 … 296.729 317.265 22.1889 + 10.8253 64.1205 89.7788 … 296.729 317.265 8.94436 ``` """ function getMeanFreq(sc::stFlux{1}, δt=1000)