@@ -266,3 +266,135 @@ def test_extract_dye_mapping() -> None:
266266 root_missing_attrs , ns
267267 )
268268 assert result_missing_attrs == {}
269+
270+
271+ @pytest .mark .parametrize (
272+ ("color_int" , "expected" ),
273+ [
274+ (0xFF0000 , (1.0 , 0.0 , 0.0 )), # Red
275+ (0x00FF00 , (0.0 , 1.0 , 0.0 )), # Green
276+ (0x0000FF , (0.0 , 0.0 , 1.0 )), # Blue
277+ (- 1 , (1.0 , 1.0 , 1.0 )), # White (unsigned 32-bit)
278+ ],
279+ )
280+ def test_int_to_rgb (color_int : int , expected : tuple [float , float , float ]) -> None :
281+ """Test conversion of integer color values to normalized RGB tuples."""
282+ result = wsireader .TIFFWSIReader ._int_to_rgb (color_int )
283+ assert pytest .approx (result ) == expected
284+
285+
286+ def test_parse_channel_data () -> None :
287+ """Test parsing of channel metadata with valid color values."""
288+ xml = """
289+ <OME xmlns="http://www.openmicroscopy.org/Schemas/OME/2016-06">
290+ <Image>
291+ <Pixels>
292+ <Channel ID="Channel:0" Name="DAPI" Color="16711680"/>
293+ <Channel ID="Channel:1" Name="FITC" Color="65280"/>
294+ </Pixels>
295+ </Image>
296+ </OME>
297+ """
298+ root = ElementTree .fromstring (xml )
299+ ns = {"ns" : "http://www.openmicroscopy.org/Schemas/OME/2016-06" }
300+ dye_mapping = {
301+ "Channel:0" : "DAPI" ,
302+ "Channel:1" : "FITC" ,
303+ }
304+
305+ result = wsireader .TIFFWSIReader ._parse_channel_data (root , ns , dye_mapping )
306+ assert result == [
307+ {
308+ "id" : "Channel:0" ,
309+ "name" : "DAPI" ,
310+ "rgb" : (1.0 , 0.0 , 0.0 ),
311+ "dye" : "DAPI" ,
312+ "label" : "Channel:0: DAPI (DAPI)" ,
313+ },
314+ {
315+ "id" : "Channel:1" ,
316+ "name" : "FITC" ,
317+ "rgb" : (0.0 , 1.0 , 0.0 ),
318+ "dye" : "FITC" ,
319+ "label" : "Channel:1: FITC (FITC)" ,
320+ },
321+ ]
322+
323+
324+ def test_parse_channel_data_with_invalid_color () -> None :
325+ """Test parsing of channel metadata with an invalid color value."""
326+ xml = """
327+ <OME xmlns="http://www.openmicroscopy.org/Schemas/OME/2016-06">
328+ <Image>
329+ <Pixels>
330+ <Channel ID="Channel:0" Name="DAPI" Color="16711680"/>
331+ <Channel ID="Channel:1" Name="FITC" Color="not_a_number"/>
332+ </Pixels>
333+ </Image>
334+ </OME>
335+ """
336+ root = ElementTree .fromstring (xml )
337+ ns = {"ns" : "http://www.openmicroscopy.org/Schemas/OME/2016-06" }
338+ dye_mapping = {
339+ "Channel:0" : "DAPI" ,
340+ "Channel:1" : "FITC" ,
341+ }
342+
343+ result = wsireader .TIFFWSIReader ._parse_channel_data (root , ns , dye_mapping )
344+ assert result == [
345+ {
346+ "id" : "Channel:0" ,
347+ "name" : "DAPI" ,
348+ "dye" : "DAPI" ,
349+ "rgb" : (1.0 , 0.0 , 0.0 ),
350+ "label" : "Channel:0: DAPI (DAPI)" ,
351+ },
352+ {
353+ "id" : "Channel:1" ,
354+ "name" : "FITC" ,
355+ "dye" : "FITC" ,
356+ "rgb" : None ,
357+ "label" : "Channel:1: FITC (FITC)" ,
358+ },
359+ ]
360+
361+
362+ def test_build_color_dict () -> None :
363+ """Test building of color dictionary with duplicate channel names."""
364+ channel_data = [
365+ {
366+ "id" : "Channel:0" ,
367+ "name" : "DAPI" ,
368+ "rgb" : (1.0 , 0.0 , 0.0 ),
369+ "dye" : "DAPI" ,
370+ "label" : "Channel:0: DAPI (DAPI)" ,
371+ },
372+ {
373+ "id" : "Channel:1" ,
374+ "name" : "DAPI" ,
375+ "rgb" : (0.0 , 1.0 , 0.0 ),
376+ "dye" : "DAPI" ,
377+ "label" : "Channel:1: DAPI (DAPI)" ,
378+ },
379+ {
380+ "id" : "Channel:2" ,
381+ "name" : "FITC" ,
382+ "rgb" : (0.0 , 0.0 , 1.0 ),
383+ "dye" : "FITC" ,
384+ "label" : "Channel:2: FITC (FITC)" ,
385+ },
386+ ]
387+
388+ dye_mapping = {
389+ "Channel:0" : "DAPI" ,
390+ "Channel:1" : "DAPI" ,
391+ "Channel:2" : "FITC" ,
392+ }
393+
394+ result = wsireader .TIFFWSIReader ._build_color_dict (channel_data , dye_mapping )
395+
396+ assert result == {
397+ "DAPI (DAPI)" : (1.0 , 0.0 , 0.0 ),
398+ "DAPI (DAPI) [2]" : (0.0 , 1.0 , 0.0 ),
399+ "FITC (FITC)" : (0.0 , 0.0 , 1.0 ),
400+ }
0 commit comments