Skip to content

Commit

Permalink
Plotting
Browse files Browse the repository at this point in the history
Added plotting functionality with ScottPlot.
  • Loading branch information
BiologyTools committed Jun 19, 2023
1 parent 3a57cc0 commit 9edb4e2
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 14 deletions.
13 changes: 6 additions & 7 deletions BioGTK.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<Platforms>AnyCPU;x64;ARM64</Platforms>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<PlatformTarget>x64</PlatformTarget>
<PackageReleaseNotes>Updated Bioformats to 6.13.0.</PackageReleaseNotes>
<PackageReleaseNotes>GUI bug fixes.</PackageReleaseNotes>
<Authors>ErikRepo</Authors>
</PropertyGroup>

Expand Down Expand Up @@ -53,6 +53,7 @@
<ItemGroup>
<Content Remove="C:\Users\Erikr\.nuget\packages\bioformats.net6\6.12.0\contentFiles\any\net6.0\bioformats_package.dll" />
<Content Remove="C:\Users\Erikr\.nuget\packages\bioformats.net6\6.13.0\contentFiles\any\net6.0\bioformats_package.dll" />
<Content Remove="C:\Users\Erikr\.nuget\packages\bioformats.net6\6.13.1\contentFiles\any\net6.0\bioformats_package.dll" />
</ItemGroup>
<ItemGroup>
<None Remove="bioformats_package.dll" />
Expand All @@ -70,6 +71,8 @@
<None Remove="Glade\Magic.glade" />
<None Remove="Glade\NodeView.glade" />
<None Remove="Glade\Play.glade" />
<None Remove="Glade\Plot.glade" />
<None Remove="Glade\Plot.glade~RF53a42aa.TMP" />
<None Remove="Glade\Progress.glade" />
<None Remove="Glade\Recorder.glade" />
<None Remove="Glade\Resolutions.glade" />
Expand Down Expand Up @@ -224,6 +227,7 @@
<EmbeddedResource Include="Glade\Magic.glade" />
<EmbeddedResource Include="Glade\NodeView.glade" />
<EmbeddedResource Include="Glade\Play.glade" />
<EmbeddedResource Include="Glade\Plot.glade" />
<EmbeddedResource Include="Glade\Progress.glade" />
<EmbeddedResource Include="Glade\Recorder.glade" />
<EmbeddedResource Include="Glade\Resolutions.glade" />
Expand Down Expand Up @@ -253,6 +257,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="ScottPlot" Version="4.1.64" />
</ItemGroup>

<ItemGroup>
Expand All @@ -272,10 +277,4 @@
</Reference>
</ItemGroup>

<ItemGroup>
<Content Update="C:\Users\Erikr\.nuget\packages\bioformats.net6\6.13.1\contentFiles\any\net6.0\bioformats_package.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

</Project>
14 changes: 14 additions & 0 deletions Glade/Plot.glade
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="plot">
<property name="can-focus">False</property>
<child>
<object class="GtkDrawingArea" id="image">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
</object>
</interface>
8 changes: 8 additions & 0 deletions Glade/TabsView.glade
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,14 @@
<property name="use-stock">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="focusMenu">
<property name="label" translatable="yes">Find Focus</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-stock">False</property>
</object>
</child>
</object>
</child>
</object>
Expand Down
10 changes: 9 additions & 1 deletion Glade/TabsView.glade~
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,14 @@
<property name="use-stock">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="focus">
<property name="label" translatable="yes">Find Focus</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-stock">False</property>
</object>
</child>
</object>
</child>
</object>
Expand Down Expand Up @@ -455,7 +463,7 @@
</object>
</child>
<child>
<object class="GtkMenuItem">
<object class="GtkMenuItem" id="scriptRecorderMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Script Recorder</property>
Expand Down
69 changes: 69 additions & 0 deletions Source/Bio.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6937,6 +6937,75 @@ public static void AutoThresholdThread(BioImage b)
Thread th = new Thread(AutoThreshold);
th.Start();
}
/// The function finds the focus of a given BioImage at a specific channel and time by
/// calculating the focus quality of each Z-plane and returning the coordinate with the highest
/// focus quality.
///
/// @param BioImage A BioImage object that contains the image data.
/// @param Channel The channel of the BioImage to analyze. A BioImage can have multiple
/// channels, each representing a different fluorescent label or imaging modality.
/// @param Time The time point at which the focus is being calculated.
///
/// @return an integer value which represents the coordinate of the image with the highest focus
/// quality in a given channel and time.
public static int FindFocus(BioImage im, int Channel, int Time)
{

long mf = 0;
int fr = 0;
List<double> dt = new List<double>();
ZCT c = new ZCT(0, 0, 0);
for (int i = 0; i < im.SizeZ; i++)
{
long f = CalculateFocusQuality(im.Buffers[im.Coords[i, Channel, Time]]);
dt.Add(f);
if (f > mf)
{
mf = f;
fr = im.Coords[i, Channel, Time];
}
}
Plot pl = Plot.Create(dt.ToArray(), "Focus");
pl.Show();
return fr;
}
/// The function calculates the focus quality of a given bitmap image.
///
/// @param Bitmap A class representing a bitmap image, which contains information about the
/// image's size, pixel data, and color channels.
///
/// @return The method is returning a long value which represents the calculated focus quality
/// of the input Bitmap image.
static long CalculateFocusQuality(Bitmap b)
{
if (b.RGBChannelsCount == 1)
{
long sum = 0;
long sumOfSquaresR = 0;
for (int y = 0; y < b.SizeY; y++)
for (int x = 0; x < b.SizeX; x++)
{
ColorS pixel = b.GetPixel(x, y);
sum += pixel.R;
sumOfSquaresR += pixel.R * pixel.R;
}
return sumOfSquaresR * b.SizeX * b.SizeY - sum * sum;
}
else
{
long sum = 0;
long sumOfSquares = 0;
for (int y = 0; y < b.SizeY; y++)
for (int x = 0; x < b.SizeX; x++)
{
ColorS pixel = b.GetPixel(x, y);
int p = (pixel.R + pixel.G + pixel.B) / 3;
sum += p;
sumOfSquares += p * p;
}
return sumOfSquares * b.SizeX * b.SizeY - sum * sum;
}
}
/// It disposes of all the buffers and channels in the image, removes the image from the Images
/// list, and then forces the garbage collector to run
public void Dispose()
Expand Down
127 changes: 127 additions & 0 deletions Source/Plot.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AForge;
using Gdk;
using GLib;
using Gtk;
using org.checkerframework.checker.units.qual;
using ScottPlot;
using System.Threading;

namespace BioGTK
{
public class Plot : Gtk.Window
{
public ScottPlot.Plot plot;
string file;
string name;
Bitmap bitmap;
List<double[]> data = new List<double[]>();
static Dictionary<string, Plot> plots = new Dictionary<string, Plot>();
public static Dictionary<string,Plot> Plots
{
get { return plots; }
}
public List<double[]> Data
{
get { return data; }
set { data = value; UpdateImage(); }
}
public Bitmap Image
{
get { return bitmap; }
set { bitmap = value; }
}
public void UpdateImage()
{
plot = new ScottPlot.Plot(AllocatedWidth, AllocatedHeight);
foreach (double[] val in data)
{
plot.AddBar(val);
}
file = plot.SaveFig(name + ".png");
this.Title = name;
pixbuf = new Pixbuf(file);
}

#region Properties
Pixbuf pixbuf;
private Builder _builder;
#pragma warning disable 649
[Builder.Object]
private Gtk.DrawingArea image;
[Builder.Object]
private Gtk.Label label;
#pragma warning restore 649
#endregion

#region Constructors / Destructors

/// It creates a new instance of the Plot class.
///
/// @return A new instance of the Plot class.
public static Plot Create(double[] vals, string name)
{
Builder builder = new Builder(null, "BioGTK.Glade.Plot.glade", null);
return new Plot(builder, builder.GetObject("plot").Handle, vals, name);
}


/* It's the constructor of the class. */
protected Plot(Builder builder, IntPtr handle, double[] vals, string name) : base(handle)
{
_builder = builder;
builder.Autoconnect(this);
this.Title = name;
image.Drawn += Image_Drawn;
image.SizeAllocated += Image_SizeAllocated;
this.DeleteEvent += About_DeleteEvent;
data.Add(vals);
this.name = name;
selected = this;
if(plots.ContainsKey(name))
plots[name] = this;
else
plots.Add(name,this);
}
System.Threading.Thread th;
static Plot selected;
public static Plot SelectedPlot
{
get { return selected; }
}
static void ShowPlot()
{
selected.Show();
selected.Present();
}

private void Image_SizeAllocated(object o, SizeAllocatedArgs args)
{
UpdateImage();
}

private void About_DeleteEvent(object o, DeleteEventArgs args)
{
args.RetVal = true;
plots.Remove(name);
Hide();
}

private void Image_Drawn(object o, DrawnArgs e)
{
Pixbuf pf = pixbuf.ScaleSimple(image.AllocatedWidth, image.AllocatedHeight, InterpType.Bilinear);
Gdk.CairoHelper.SetSourcePixbuf(e.Cr, pf, 0, 0);
e.Cr.Paint();
e.Cr.Stroke();
}

#endregion

}
}
2 changes: 2 additions & 0 deletions Source/Scripting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ public void Stop()
return;
//We stop this script
SelectedItem.Stop();
RefreshItems();
}
/// It runs the program.
///
Expand Down Expand Up @@ -752,6 +753,7 @@ private void Save()
scripts.Add(scriptLabel.Text,new Script(filechooser.Filename, view.Buffer.Text));
}
RefreshItems();
filechooser.Destroy();
}

/// It stops the timer and resets the timer to 0
Expand Down
23 changes: 17 additions & 6 deletions Source/TabsView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ public static ImageView SelectedViewer
private MenuItem rotateFlipMenu;
[Builder.Object]
private MenuItem stackToolMenu;

[Builder.Object]
private MenuItem focusMenu;

[Builder.Object]
private MenuItem to8BitMenu;
Expand Down Expand Up @@ -217,6 +218,7 @@ protected void SetupHandlers()
switchRedBlueMenu.ButtonPressEvent += switchRedBlueMenuClick;

stackToolMenu.ButtonPressEvent += stackToolMenuClick;
focusMenu.ButtonPressEvent += FocusMenu_ButtonPressEvent;

to8BitMenu.ButtonPressEvent += to8BitMenuClick;
to16BitMenu.ButtonPressEvent += to16BitMenuClick;
Expand All @@ -241,11 +243,20 @@ protected void SetupHandlers()
this.WindowStateEvent += TabsView_WindowStateEvent;
}

/// When the user clicks on the Script Recorder menu item, the Script Recorder window is shown
///
/// @param o The object that the event is being called on.
/// @param ButtonPressEventArgs
/// https://developer.gnome.org/gtk3/stable/GtkButton.html#GtkButton-clicked
private void FocusMenu_ButtonPressEvent(object o, ButtonPressEventArgs args)
{
if (ImageView.SelectedImage == null) return;
ZCT co = SelectedViewer.GetCoordinate();
int f = BioImage.FindFocus(ImageView.SelectedImage, co.C, co.T);
ZCT z = ImageView.SelectedImage.Buffers[f].Coordinate;
SelectedViewer.SetCoordinate(z.Z, z.C, z.T);
}

/// When the user clicks on the Script Recorder menu item, the Script Recorder window is shown
///
/// @param o The object that the event is being called on.
/// @param ButtonPressEventArgs
/// https://developer.gnome.org/gtk3/stable/GtkButton.html#GtkButton-clicked
private void ScriptRecorderMenu_ButtonPressEvent(object o, ButtonPressEventArgs args)
{
App.recorder.Show();
Expand Down

0 comments on commit 9edb4e2

Please sign in to comment.