BioImager  5.0.0
A .NET microscopy imaging application based on Bio library. Supports various microscopes by using imported libraries & GUI automation. Supports XInput game controllers to move stage, take images, run ImageJ macros on images or Bio C# scripts.
Loading...
Searching...
No Matches
ChannelsTool.cs
Go to the documentation of this file.
1using AForge;
2using BioLib;
3using System;
4using System.Collections.Generic;
5using System.ComponentModel;
6using System.Drawing;
7using System.Drawing.Imaging;
8using System.Windows.Forms;
9namespace BioImager
10{
11 public partial class ChannelsTool : Form
12 {
13 private HistogramControl hist = null;
14 private bool initializing;
15 private int histogramRequestVersion;
16 private BioLib.BioImage histogramLoadingImage;
17 private Task histogramLoadingTask;
18 private BioLib.BioImage histogramImage;
19 private ZCT histogramCoordinate;
20 private ZCT histogramLoadingCoordinate;
21 public List<Channel> Channels
22 {
23 get
24 {
25 return App.Channels;
26 }
27 }
28 /* A property that returns the selected channel from the channelsBox. */
29 public Channel SelectedChannel
30 {
31 get
32 {
33 if (channelsBox.SelectedIndex != -1)
34 return Channels[channelsBox.SelectedIndex];
35 else
36 return Channels[0];
37 }
38 }
39 /* A property that is used to get and set the value of the sampleBox.Value. */
40 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
41 public int SelectedSample
42 {
43 get
44 {
45 return (int)sampleBox.Value;
46 }
47 set
48 {
49 sampleBox.Value = (decimal)value;
50 }
51 }
53 public void UpdateItems()
54 {
55 int selectedIndex = channelsBox.SelectedIndex;
56 initializing = true;
57 channelsBox.Items.Clear();
58 foreach (Channel item in Channels)
59 {
60 channelsBox.Items.Add(item);
61 }
62 channelsBox.SelectedIndex = Channels.Count == 0
63 ? -1
64 : Math.Clamp(selectedIndex, 0, Channels.Count - 1);
65 initializing = false;
66 }
67 /* Creating a new instance of the ChannelsTool class. */
68 public ChannelsTool(List<Channel> Channels)
69 {
70 initializing = true;
71 InitializeComponent();
72 foreach (Channel item in Channels)
73 {
74 channelsBox.Items.Add(item);
75 }
76 MouseWheel += new System.Windows.Forms.MouseEventHandler(ChannelsTool_MouseWheel);
77
78 if (Channels.Count == 0)
79 {
80 channelsBox.Enabled = false;
81 sampleBox.Enabled = false;
82 statsPanel.Controls.Add(new Label
83 {
84 Dock = DockStyle.Fill,
85 Text = "No channel metadata is available for this image.",
86 TextAlign = ContentAlignment.MiddleCenter
87 });
88 initializing = false;
89 return;
90 }
91
92 channelsBox.SelectedIndex = 0;
93 Channel channel = Channels[0];
94 int sample = channel.range?.Length > 0 ? 0 : -1;
95 int defaultMax = channel.BitsPerPixel <= 8 ? byte.MaxValue : ushort.MaxValue;
96 int minimum = sample >= 0 ? channel.range[sample].Min : 0;
97 int maximum = sample >= 0 ? channel.range[sample].Max : defaultMax;
98 if (channel.stats?.Length > 0)
99 {
100 minimum = (int)channel.stats[0].StackMin;
101 maximum = (int)channel.stats[0].StackMax;
102 }
103 minBox.Value = Math.Clamp(minimum, (int)minBox.Minimum, (int)minBox.Maximum);
104 maxBox.Value = Math.Clamp(maximum, (int)maxBox.Minimum, (int)maxBox.Maximum);
105 hist = new HistogramControl(channel);
106 hist.GraphMax = Math.Max(1, (int)maxBox.Value);
107 maxGraphBox.Value = Math.Clamp(maxBox.Value, maxGraphBox.Minimum, maxGraphBox.Maximum);
108 statsPanel.Controls.Add(hist);
109 initializing = false;
110 Shown += async (_, _) => await EnsureHistogramAsync();
111 }
112
120 private void minBox_ValueChanged(object sender, EventArgs e)
121 {
122 if (initializing || channelsBox.SelectedIndex == -1)
123 return;
124 if (hist != null)
125 {
126 hist.UpdateChannel(Channels[channelsBox.SelectedIndex]);
127 hist.Invalidate();
128 hist.Min = (int)minBox.Value;
129 }
130 App.Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min = (int)minBox.Value;
131 App.viewer.UpdateImage();
132 App.viewer.UpdateView();
133 }
141 private void maxBox_ValueChanged(object sender, EventArgs e)
142 {
143 if (initializing || channelsBox.SelectedIndex == -1)
144 return;
145 if (hist != null)
146 {
147 hist.UpdateChannel(Channels[channelsBox.SelectedIndex]);
148 hist.Invalidate();
149 hist.Max = (int)maxBox.Value;
150 }
151 App.Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min = (int)minBox.Value;
152 App.viewer.UpdateImage();
153 App.viewer.UpdateView();
154 }
162 private void channelsBox_SelectedIndexChanged(object sender, EventArgs e)
163 {
164 if (initializing || channelsBox.SelectedIndex == -1)
165 return;
166 Channel channel = Channels[channelsBox.SelectedIndex];
167 if (channel.range == null || channel.range.Length == 0)
168 return;
169 sampleBox.Value = 0;
170 sampleBox.Maximum = channel.range.Length - 1;
171 if (minBox.Maximum < Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min || maxBox.Maximum < Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Max)
172 {
173 minBox.Value = 0;
174 maxBox.Value = ushort.MaxValue;
175 }
176 else
177 {
178 minBox.Value = Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min;
179 maxBox.Value = Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Max;
180 }
181 if (hist != null)
182 {
183 //hist.Statistics = Channels[channelsBox.SelectedIndex].statistics;
184 hist.UpdateChannel(SelectedChannel);
185 hist.Invalidate();
186 }
187 fluorBox.Text = SelectedChannel.Fluor;
188 emisBox.Value = (decimal)SelectedChannel.Emission;
189 excBox.Value = (decimal)SelectedChannel.Excitation;
190 App.viewer.UpdateView();
191 }
197
198 private void maxUintBox_SelectedIndexChanged(object sender, EventArgs e)
199 {
200 int i = int.Parse((string)maxUintBox.SelectedItem,System.Globalization.CultureInfo.InvariantCulture);
201 if(i<=maxBox.Maximum)
202 maxBox.Value = i;
203
204 }
205
210 private void ChannelsTool_FormClosing(object sender, FormClosingEventArgs e)
211 {
212 e.Cancel = true;
213 this.Hide();
214 }
215
220 private void setMaxAllBut_Click(object sender, EventArgs e)
221 {
222 foreach (Channel c in Channels)
223 {
224 for (int i = 0; i < c.range.Length; i++)
225 {
226 c.range[i].Max = (int)maxBox.Value;
227 }
228 }
229 App.viewer.UpdateView();
230 }
231
236 private void setMinAllBut_Click(object sender, EventArgs e)
237 {
238 foreach (Channel c in Channels)
239 {
240 for (int i = 0; i < c.range.Length; i++)
241 {
242 c.range[i].Min = (int)minBox.Value;
243 }
244 }
245 App.viewer.UpdateView();
246 }
247
253 private void ChannelsTool_Activated(object sender, EventArgs e)
254 {
255 UpdateItems();
256 if (Channels.Count == 0 || channelsBox.SelectedIndex < 0 || hist == null)
257 return;
258 Channel channel = SelectedChannel;
259 if (channel.range == null || channel.range.Length == 0)
260 return;
261 initializing = true;
262 sampleBox.Maximum = channel.range.Length - 1;
263 sampleBox.Value = Math.Min(sampleBox.Value, sampleBox.Maximum);
264 minBox.Value = Math.Clamp(channel.range[(int)sampleBox.Value].Min,
265 (int)minBox.Minimum, (int)minBox.Maximum);
266 maxBox.Value = Math.Clamp(channel.range[(int)sampleBox.Value].Max,
267 (int)maxBox.Minimum, (int)maxBox.Maximum);
268 initializing = false;
269 hist.UpdateChannel(channel);
270 hist.UpdateView();
271 _ = EnsureHistogramAsync();
272
273 }
274
279 private async Task EnsureHistogramAsync()
280 {
281 BioImage image = ImageView.SelectedImage;
282 if (IsDisposed || Disposing || image == null || hist == null || hist.IsDisposed)
283 return;
284
285 ZCT coordinate = image.Coordinate;
286 int requestVersion = ++histogramRequestVersion;
287 if (ReferenceEquals(histogramImage, image) && SameCoordinate(histogramCoordinate, coordinate) &&
288 ZarrChannelView.HasHistogramStatistics(image))
289 {
290 hist.StatusMessage = "";
291 hist.Invalidate();
292 return;
293 }
294
295 hist.StatusMessage = "Loading histogram…";
296 hist.Invalidate();
297 try
298 {
299 if (!ReferenceEquals(histogramLoadingImage, image) ||
300 !SameCoordinate(histogramLoadingCoordinate, coordinate) ||
301 histogramLoadingTask == null || histogramLoadingTask.IsCompleted)
302 {
303 histogramLoadingImage = image;
304 histogramLoadingCoordinate = coordinate;
305 histogramLoadingTask = ZarrChannelView.EnsureHistogramStatisticsAsync(
306 image, coordinate);
307 }
308 await histogramLoadingTask;
309 if (IsDisposed || Disposing || requestVersion != histogramRequestVersion || image != ImageView.SelectedImage)
310 return;
311 histogramImage = image;
312 histogramCoordinate = coordinate;
313 hist.StatusMessage = ZarrChannelView.HasHistogramStatistics(image)
314 ? ""
315 : "Histogram data is unavailable for this image.";
316 hist.UpdateChannel(SelectedChannel);
317 ApplyFrameRange();
318 hist.Invalidate();
319 }
320 catch (Exception ex)
321 {
322 if (requestVersion != histogramRequestVersion)
323 return;
324 hist.StatusMessage = $"Could not load histogram: {ex.Message}";
325 hist.Invalidate();
326 }
327 }
328
329 public void RefreshHistogram()
330 {
331 if (Visible)
332 _ = EnsureHistogramAsync();
333 }
334
335 private void ApplyFrameRange()
336 {
337 if (channelsBox.SelectedIndex < 0 || SelectedChannel.stats == null ||
338 SelectedChannel.stats.Length == 0)
339 return;
340
341 int sample = Math.Clamp((int)sampleBox.Value, 0, SelectedChannel.stats.Length - 1);
342 Statistics statistics = SelectedChannel.stats[sample];
343 int minimum = Math.Clamp((int)statistics.StackMin, (int)minBox.Minimum, (int)minBox.Maximum);
344 int maximum = Math.Clamp((int)statistics.StackMax, minimum, (int)maxBox.Maximum);
345 int graphMaximum = Math.Max(1, maximum);
346 int graphMinimum = Math.Min(minimum, graphMaximum);
347 int histogramBin = Math.Max(1, (graphMaximum - graphMinimum + 255) / 256);
348
349 initializing = true;
350 minBox.Value = minimum;
351 maxBox.Value = maximum;
352 minGraphBox.Value = Math.Clamp(graphMinimum,
353 (int)minGraphBox.Minimum, (int)minGraphBox.Maximum);
354 maxGraphBox.Value = Math.Clamp(graphMaximum,
355 (int)maxGraphBox.Minimum, (int)maxGraphBox.Maximum);
356 binBox.Value = Math.Clamp(histogramBin, (int)binBox.Minimum, (int)binBox.Maximum);
357 initializing = false;
358
359 hist.GraphMin = graphMinimum;
360 hist.GraphMax = graphMaximum;
361 hist.Bin = histogramBin;
362 }
363
364 private static bool SameCoordinate(ZCT left, ZCT right) =>
365 left.Z == right.Z && left.C == right.C && left.T == right.T;
366
367 private void ChannelsTool_ResizeEnd(object sender, EventArgs e)
368 {
369 hist?.UpdateView();
370 }
371
377 private void maxUintBox2_SelectedIndexChanged(object sender, EventArgs e)
378 {
379 int i = int.Parse((string)maxUintBox2.SelectedItem, System.Globalization.CultureInfo.InvariantCulture);
380 if(i <= maxGraphBox.Maximum)
381 maxGraphBox.Value = i;
382 if (i == 255)
383 {
384 maxGraphBox.Value = 255;
385 binBox.Value = 1;
386 }
387 }
388
394 private void minGraphBox_ValueChanged(object sender, EventArgs e)
395 {
396 if (hist != null)
397 {
398 hist.GraphMin = (int)minGraphBox.Value;
399 hist.Invalidate();
400 }
401 }
402
408 private void maxGraphBox_ValueChanged(object sender, EventArgs e)
409 {
410 if (hist != null)
411 {
412 hist.GraphMax = (int)maxGraphBox.Value;
413 hist.Invalidate();
414 }
415 }
421 private void binBox_ValueChanged(object sender, EventArgs e)
422 {
423 if (hist != null)
424 {
425 hist.Bin = (int)binBox.Value;
426 hist.Invalidate();
427 }
428 }
429
434 private void ChannelsTool_MouseDown(object sender, MouseEventArgs e)
435 {
436
437 }
438 private bool pressedX1 = false;
439 private bool pressedX2 = false;
449 private void ChannelsTool_MouseMove(object sender, MouseEventArgs e)
450 {
451 if (e.Button == MouseButtons.XButton1)
452 {
453 if (channelsBox.SelectedIndex < channelsBox.Items.Count-1)
454 {
455 if (pressedX1 == false)
456 {
457 channelsBox.SelectedIndex++;
458 pressedX1 = true;
459 return;
460 }
461 }
462 }
463 pressedX1 = false;
464 if (e.Button == MouseButtons.XButton2)
465 {
466 if (channelsBox.SelectedIndex > 0)
467 {
468 if (pressedX2 == false)
469 {
470 channelsBox.SelectedIndex--;
471 pressedX2 = true;
472 return;
473 }
474 }
475 }
476 pressedX2 = false;
477 }
478
487 private void ChannelsTool_MouseWheel(object sender, MouseEventArgs e)
488 {
489 if (e.Delta == 0)
490 return;
491 int i = 100;
492 if (maxGraphBox.Value < 255)
493 i = 10;
494 if (e.Delta > 0)
495 {
496 if (maxGraphBox.Value + i < maxGraphBox.Maximum)
497 {
498 maxGraphBox.Value += i;
499 hist.Invalidate();
500 return;
501 }
502 }
503 else
504 if (maxGraphBox.Value - i > maxGraphBox.Minimum)
505 {
506 maxGraphBox.Value -= i;
507 hist.Invalidate();
508 return;
509 }
510 }
511
516 private void stackHistoBox_CheckedChanged(object sender, EventArgs e)
517 {
518 hist.StackHistogram = stackHistoBox.Checked;
519 hist.Invalidate();
520 }
521
527 private void setMinToolStripMenuItem_Click(object sender, EventArgs e)
528 {
529 minBox.Value = (int)hist.MouseValX;
530 }
531
537 private void setMaxToolStripMenuItem_Click(object sender, EventArgs e)
538 {
539 maxBox.Value = (int)hist.MouseValX;
540 }
541
547 private void applyBut_Click(object sender, EventArgs e)
548 {
549 ImageView.SelectedImage.Bake(ImageView.SelectedImage.RChannel.RangeR, ImageView.SelectedImage.GChannel.RangeG, ImageView.SelectedImage.BChannel.RangeB);
550 }
551
552 private void minToolStripMenuItem_Click(object sender, EventArgs e)
553 {
554 minBox.Value = (decimal)SelectedChannel.stats[channelsBox.SelectedIndex].StackMin;
555 }
556
557 private void maxToolStripMenuItem_Click(object sender, EventArgs e)
558 {
559 minBox.Value = (decimal)SelectedChannel.stats[channelsBox.SelectedIndex].StackMax;
560 }
561
562 private void medianToolStripMenuItem_Click(object sender, EventArgs e)
563 {
564 minBox.Value = (decimal)SelectedChannel.stats[channelsBox.SelectedIndex].StackMedian;
565 }
566
567 private void meanToolStripMenuItem_Click(object sender, EventArgs e)
568 {
569 minBox.Value = (decimal)SelectedChannel.stats[channelsBox.SelectedIndex].StackMean;
570 }
571
572 private void toolStripMenuItem1_Click(object sender, EventArgs e)
573 {
574 maxBox.Value = (decimal)SelectedChannel.stats[channelsBox.SelectedIndex].StackMin;
575 }
576
577 private void toolStripMenuItem2_Click(object sender, EventArgs e)
578 {
579 maxBox.Value = (decimal)SelectedChannel.stats[channelsBox.SelectedIndex].StackMax;
580 }
581 private void toolStripMenuItem3_Click(object sender, EventArgs e)
582 {
583 maxBox.Value = (decimal)SelectedChannel.stats[channelsBox.SelectedIndex].StackMedian;
584 }
585 private void toolStripMenuItem4_Click(object sender, EventArgs e)
586 {
587 maxBox.Value = (decimal)SelectedChannel.stats[channelsBox.SelectedIndex].StackMean;
588 }
589
594 private void updateBut_Click(object sender, EventArgs e)
595 {
596 if (ImageView.SelectedImage.bitsPerPixel > 8)
597 {
598 ImageView.SelectedImage.StackThreshold(true);
599 if (ImageView.SelectedImage.RGBChannelCount == 1)
600 {
601 maxBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[0].StackMax;
602 minBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[0].StackMin;
603 }
604 else
605 {
606 maxBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[channelsBox.SelectedIndex].StackMax;
607 minBox.Value = (decimal)ImageView.SelectedImage.Channels[channelsBox.SelectedIndex].stats[channelsBox.SelectedIndex].StackMin;
608 }
609 }
610 else
611 {
612 ImageView.SelectedImage.StackThreshold(false);
613 }
614 App.viewer.UpdateImage();
615 }
616
622 private void sampleBox_ValueChanged(object sender, EventArgs e)
623 {
624 if (initializing || channelsBox.SelectedIndex == -1)
625 channelsBox.SelectedIndex = 0;
626 minBox.Value = Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Min;
627 maxBox.Value = Channels[channelsBox.SelectedIndex].range[(int)sampleBox.Value].Max;
628 if (hist != null)
629 {
630 //hist.Statistics = Channels[channelsBox.SelectedIndex].statistics;
631 hist.UpdateChannel(SelectedChannel);
632 hist.Invalidate();
633 }
634 App.viewer.UpdateView();
635 }
636
637 private void excBox_ValueChanged(object sender, EventArgs e)
638 {
639 SelectedChannel.Excitation = (int)excBox.Value;
640 }
641
642 private void emisBox_ValueChanged(object sender, EventArgs e)
643 {
644 SelectedChannel.Emission = (int)emisBox.Value;
645 }
646
647 private void fluorBox_TextChanged(object sender, EventArgs e)
648 {
649 SelectedChannel.Fluor = fluorBox.Text;
650 }
651 }
652}
BioLib.BioImage BioImage
Definition TabsView.cs:15
AForge.ZCT ZCT
Definition TabsView.cs:17
static List< Channel > Channels
Definition App.cs:68
void UpdateItems()
It clears the listbox and then adds all the items in the Channels list to the listbox.
List< Channel > Channels
ChannelsTool(List< Channel > Channels)