-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathHttpExamples.cs
More file actions
333 lines (260 loc) · 12.9 KB
/
Copy pathHttpExamples.cs
File metadata and controls
333 lines (260 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
using ZarrNET.Core.Helpers;
using ZarrNET;
using ZarrNET.Core;
using ZarrNET.Core.OmeZarr;
using ZarrNET.Core.Zarr.Store;
// =============================================================================
// Example 1 — Read from public HTTP URL
// =============================================================================
namespace ZarrNET
{
public class Reader
{
async Task ReadFromPublicUrl()
{
// OME-Zarr datasets can be hosted on any HTTP server
var url = "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001240.zarr";
await using var reader = await OmeZarrReader.OpenAsync(url);
var image = reader.AsMultiscaleImage();
var multiscale = image.Multiscales[0];
Console.WriteLine($"Remote image: {multiscale.Name}");
Console.WriteLine($"Axes: {string.Join(", ", multiscale.Axes.Select(a => a.Name))}");
Console.WriteLine($"Resolution levels: {multiscale.Datasets.Length}");
// Open a low-resolution level for fast preview
var level = await image.OpenResolutionLevelAsync(datasetIndex: 2);
Console.WriteLine($"Level 2 shape: [{string.Join(", ", level.Shape)}]");
// Read a small region
var plane = await level.ReadPlaneAsync(t: 0, c: 0, z: 0);
Console.WriteLine($"Downloaded plane: {plane}");
}
// =============================================================================
// Example 2 — Read from S3 public bucket
// =============================================================================
async Task ReadFromS3()
{
// Public S3 buckets can be accessed directly via HTTPS
var s3Url = "https://s3.amazonaws.com/my-bucket/datasets/image.zarr";
await using var reader = await OmeZarrReader.OpenAsync(s3Url);
var image = reader.AsMultiscaleImage();
var level = await image.OpenResolutionLevelAsync(0);
var plane = await level.ReadPlaneAsync(t: 0, c: 0, z: 0);
Console.WriteLine($"S3 plane: {plane}");
}
// =============================================================================
// Example 3 — Read from Azure Blob Storage
// =============================================================================
async Task ReadFromAzure()
{
// Azure Blob Storage public containers or SAS URLs
var azureUrl = "https://myaccount.blob.core.windows.net/container/image.zarr";
await using var reader = await OmeZarrReader.OpenAsync(azureUrl);
var image = reader.AsMultiscaleImage();
// Rest is the same as local files...
}
// =============================================================================
// Example 4 — Read from Google Cloud Storage
// =============================================================================
async Task ReadFromGcs()
{
// Google Cloud Storage public buckets
var gcsUrl = "https://storage.googleapis.com/my-bucket/image.zarr";
await using var reader = await OmeZarrReader.OpenAsync(gcsUrl);
// ...
}
// =============================================================================
// Example 5 — Custom HttpClient configuration (authentication, timeouts)
// =============================================================================
async Task ReadWithCustomHttpClient()
{
// Create custom HttpClient with authentication
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_TOKEN");
httpClient.Timeout = TimeSpan.FromMinutes(10);
var store = new HttpZarrStore("https://example.com/data.zarr", httpClient, ownsHttpClient: true);
await using var reader = await OmeZarrReader.OpenAsync(store);
var image = reader.AsMultiscaleImage();
// Read data...
}
// =============================================================================
// Example 6 — IDR (Image Data Resource) public datasets
// =============================================================================
async Task ReadFromIdr()
{
// IDR hosts many public OME-Zarr datasets
// Browse at: https://idr.openmicroscopy.org/
var idrUrl = "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001240.zarr";
await using var reader = await OmeZarrReader.OpenAsync(idrUrl);
var image = reader.AsMultiscaleImage();
Console.WriteLine("Reading from IDR...");
// Get metadata
var axes = image.Multiscales[0].Axes;
var omero = image.Multiscales[0].Omero;
if (omero?.Channels != null)
{
Console.WriteLine("Channels:");
foreach (var ch in omero.Channels)
{
Console.WriteLine($" {ch.Label}: color={ch.Color}, active={ch.Active}");
}
}
// Read a thumbnail from lowest resolution
var numLevels = image.Multiscales[0].Datasets.Length;
var thumbnail = await image.OpenResolutionLevelAsync(numLevels - 1);
var plane = await thumbnail.ReadPlaneAsync(t: 0, c: 0, z: 0);
Console.WriteLine($"Thumbnail: {plane.Width}x{plane.Height}");
}
// =============================================================================
// Example 7 — Progressive loading (low res → high res)
// =============================================================================
async Task ProgressiveLoading(string url)
{
await using var reader = await OmeZarrReader.OpenAsync(url);
var image = reader.AsMultiscaleImage();
var levels = await image.OpenAllResolutionLevelsAsync();
// Load from lowest to highest resolution
for (int i = levels.Count - 1; i >= 0; i--)
{
var level = levels[i];
var plane = await level.ReadPlaneAsync(t: 0, c: 0, z: 0);
Console.WriteLine($"Level {i}: {plane.Width}x{plane.Height}");
// Display progressively more detailed image
// UpdateDisplay(plane);
if (i > 0)
{
// Show low-res while loading high-res
Console.WriteLine($" Loaded {plane.Data.Length:N0} bytes, loading next level...");
}
}
Console.WriteLine("Full resolution loaded!");
}
// =============================================================================
// Example 8 — Download and cache locally
// =============================================================================
async Task DownloadAndCache(string url, string localPath)
{
Console.WriteLine($"Downloading from {url}...");
await using var httpReader = await OmeZarrReader.OpenAsync(url);
var image = httpReader.AsMultiscaleImage();
var level = await image.OpenResolutionLevelAsync(0);
// Read all data
var fullExtent = new ZarrNET.Core.OmeZarr.Coordinates.PixelRegion(
start: new long[level.Rank],
end: level.Shape
);
var data = await level.ReadPixelRegionAsync(fullExtent);
Console.WriteLine($"Downloaded {data.Data.Length:N0} bytes");
// Save to local file for caching
// (This is a simple example - for production, copy the entire Zarr structure)
System.IO.File.WriteAllBytes(localPath, data.Data);
Console.WriteLine($"Cached to {localPath}");
}
// =============================================================================
// Example 9 — Compare local vs remote performance
// =============================================================================
async Task CompareLocalVsRemote(string localPath, string remoteUrl)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
// Local read
await using (var localReader = await OmeZarrReader.OpenAsync(localPath))
{
var level = await localReader.AsMultiscaleImage().OpenResolutionLevelAsync(0);
var plane = await level.ReadPlaneAsync(t: 0, c: 0, z: 0);
sw.Stop();
Console.WriteLine($"Local read: {sw.ElapsedMilliseconds}ms ({plane.Data.Length:N0} bytes)");
}
sw.Restart();
// Remote read
await using (var remoteReader = await OmeZarrReader.OpenAsync(remoteUrl))
{
var level = await remoteReader.AsMultiscaleImage().OpenResolutionLevelAsync(0);
var plane = await level.ReadPlaneAsync(t: 0, c: 0, z: 0);
sw.Stop();
Console.WriteLine($"Remote read: {sw.ElapsedMilliseconds}ms ({plane.Data.Length:N0} bytes)");
}
}
// =============================================================================
// Example 10 — Handle network errors gracefully
// =============================================================================
async Task ReadWithErrorHandling(string url)
{
try
{
await using var reader = await OmeZarrReader.OpenAsync(url);
var image = reader.AsMultiscaleImage();
var level = await image.OpenResolutionLevelAsync(0);
var plane = await level.ReadPlaneAsync(t: 0, c: 0, z: 0);
Console.WriteLine($"Success: {plane}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Network error: {ex.Message}");
Console.WriteLine("Check your internet connection and URL.");
}
catch (TimeoutException ex)
{
Console.WriteLine($"Request timed out: {ex.Message}");
Console.WriteLine("The dataset may be very large or the server is slow.");
}
catch (FileNotFoundException ex)
{
Console.WriteLine($"Dataset not found: {ex.Message}");
Console.WriteLine("The Zarr metadata files are missing or the URL is incorrect.");
}
}
// =============================================================================
// Example 11 — Mixed local and remote (plate with remote fields)
// =============================================================================
async Task MixedLocalRemote()
{
// This demonstrates the architecture's flexibility —
// you could theoretically have a plate where some wells are local
// and others are remote, though in practice this is uncommon
var localPlate = await OmeZarrReader.OpenAsync("C:/data/plate.zarr");
var remotePlate = await OmeZarrReader.OpenAsync("https://example.com/plate.zarr");
// Both work identically
var localWell = await localPlate.AsPlate().OpenWellAsync("A", "1");
var remoteWell = await remotePlate.AsPlate().OpenWellAsync("A", "1");
}
// =============================================================================
// Example 12 — Real-world example: Load IDR dataset and find brightest region
// =============================================================================
async Task FindBrightestRegion()
{
var url = "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001240.zarr";
await using var reader = await OmeZarrReader.OpenAsync(url);
var image = reader.AsMultiscaleImage();
// Use low-resolution level for fast scanning
var level = await image.OpenResolutionLevelAsync(datasetIndex: 3);
var plane = await level.ReadPlaneAsync(t: 0, c: 0, z: 0);
Console.WriteLine($"Scanning {plane.Width}x{plane.Height} pixels...");
var pixels = plane.As1DArray<ushort>();
// Find max intensity
ushort maxValue = 0;
int maxIndex = 0;
for (int i = 0; i < pixels.Length; i++)
{
if (pixels[i] > maxValue)
{
maxValue = pixels[i];
maxIndex = i;
}
}
int y = maxIndex / plane.Width;
int x = maxIndex % plane.Width;
Console.WriteLine($"Brightest pixel at ({x}, {y}) with value {maxValue}");
var fullRes = await image.OpenResolutionLevelAsync(0);
var fullResWidth = fullRes.Shape[4]; // x is at index 4 in [t,c,z,y,x]
var scaleFactor = fullResWidth / plane.Width; // ✓ Works!
var fullResX = x * scaleFactor;
var fullResY = y * scaleFactor;
var cropSize = 512;
var cropRegion = new ZarrNET.Core.OmeZarr.Coordinates.PixelRegion(
start: [0, 0, 0, Math.Max(0, fullResY - cropSize / 2), Math.Max(0, fullResX - cropSize / 2)],
end: [1, 1, 1, Math.Min(fullRes.Shape[3], fullResY + cropSize/2),
Math.Min(fullRes.Shape[4], fullResX + cropSize/2)]
);
var crop = await fullRes.ReadPixelRegionAsync(cropRegion);
Console.WriteLine($"Loaded high-res crop: {crop}");
}
}
}