# Photomicrograph
**by [Matt Hall](https://github.com/kwinkunks)**
A **photomicrograph** is an image of an object, such as a very thin slice through a rock, taken with a microscope. We can shine light right through a 30-μm-thick slice of sandstone, and see the tiny grains of sand it's composed of. A geologist can identify the minerals present and measure the sizes of grains, all of which can help her figure out where and when the rock was deposited and what's happened to it since.
Here's an example from the Triassic of the UK in which some of the grains have been labeled with identifiers:
The data for this challenge represents an annotated photomicrograph like this one (well, a bit like it). The image has been encoded into text using a [**base64**](https://en.wikipedia.org/wiki/Base64) encoding scheme, which is easy to decode with Python. In the code that follows, `data` represents the text string you get using your key. First we convert the text to a 'byte stream', then we turn it into a file-like object with `BytesIO`, which we can then give to `plt.imread()` (which normally expects a file name).
import base64
from io import BytesIO
import matplotlib.pyplot as plt
bytestream = base64.b64decode(data)
imarray = plt.imread(BytesIO(bytestream))
The result, `imarray`, is a 3-D NumPy array with shape `(h, w, 3)`. It represents an RGB image of height h and width w, with three channels: one each for red, green and blue (e.g. the red channel is stored in `imarray[:, :, 0]`). You can plot an array like this with `plt.imshow(imarray)`; `matplotlib` correctly interprets it as an image and displays it accordingly (this only works because the last dimension is of size 1, 3 or 4).
The image has two parts: a photomicrograph, and a strip at the bottom containing a scale bar. Each colour and shade of grey in the photomicrograph represents a different mineral, **except** for the mid-grey colour of the pixels between all the circular grains — this is the 'matrix', an undifferentiated fine-grained material. Grains are always lighter in colour than the matrix. Some of the grains are various shades of grey (a pixel is grey if the values of its three channels are equal), and some of the grains have colour, although the colours are rather unsaturated and difficult to perceive. For example:
- A pixel with more red (the first channel) than any other colour, and equal amounts of green and blue, is **red**.
- A pixel with equal amounts of red and green, and less blue, would be **yellow** (red, green and blue light mix additively).
## Questions
Your challenge is to answer the following questions:
1. Not including the matrix, how many different types of grain are there in the photomicrograph?
2. What percentage of the photomicrograph is occupied by the matrix? Give your answer to **one decimal place** of precision and do not include the percent sign.
3. Count the number of **red** grains and the number of **magenta** grains. What is the product of these 2 numbers?
4. What is the diameter of the largest grain in the photomicrograph, in micrometres? Round to the nearest integer.
## Hints
This challenge will require you to get to grips with NumPy arrays and introduces you to some image processing techniques. It is likely that you will find [`scipy.ndimage`](https://docs.scipy.org/doc/scipy/reference/ndimage.html) useful, especially the functions in the `morphology` and `measurements` submodules. Read more about binary morphologies [here](https://en.wikipedia.org/wiki/Mathematical_morphology). Don't forget that each question has a hint, if you need it (see _A reminder how this works_, below).
## Example
Here's a tiny photomicrograph. It's 40 × 40 pixels, plus 5 extra pixels at the bottom for the scale. Your image will be larger, with a lot more grains, and the scale bar will be labeled with its length in micrometres, μm. I don't have enough pixels to label this one!
You can save that image to your computer, then read it with `plt.imshow('filename.png')`, or here's its base64 string, which you can load using the code I gave you eariler:
iVBORw0KGgoAAAANSUhEUgAAACgAAAAtCAIAAABTUb6JAAAA6klEQVR4nO2YQRKDIAxFodOzcgL2DHvuTBedMgwETEIEsf6ViuT5IWJQG2PUCr2WUB/wTL07bSG4/NRaj4/rXEjH3tv6Bg1mdYGksnNqi32lOW7Z7TcJgOfoXuAilU7J6lAlsFLKQiQUGGQXVBCJxzfBOZ6KxOAPwMCjUKgdNi25GNRWrx1eJ57dVt8dHK8Bj4wzGOHyjv8PjFn3SREu73gleGS06747OFZc0wKfRQZbrBBIOrf04eGHir0stPuFI2zaDkUqBMT2LyhwMirreHSO2dpkARGUjjEuAff+gQxKaw1e/1p95niaPikmXqONkuFHAAAAAElFTkSuQmCC
Here's how we'd answer the questions for this image:
1. There are **`4`** different types of grain in this image: yellow, blue, magenta, and red.
2. The image (not including the 5 pixels at the bottom) contain 1600 pixels, and the matrix occupies 1082 of them; this is **`67.6`** percent of the image.
3. There is 1 red grain (lowermost) and 1 magenta one (the largest one); the product is **`1`**.
4. The largest grain measures 23 pixels across, and the scale bar is 8 pixels long. If the scale bar's length was given as 200 micrometres, then the diameter of the largest grain would be **`575`** micrometres.
## A quick reminder how this works
This document is formatted in [Markdown](https://daringfireball.net/projects/markdown/).
You can retrieve your data, which is always a string, by choosing a **``** (also a string). This ensures that you have different data from other people, so be creative.
```
url = 'https://kata.scienxlab.org/challenge/photomicrograph'
params = {
'key': # Replace with your own string.
}
r = requests.get(url, params)
r.text
```
To answer question 1, change the `params`:
```
params = {
'key': , # Use the same key you used to get your input.
'question': 1,
'answer': 1234 # Your answer; can be a float, int, list or array;
# the challenge description will tell you which.
}
```
To get a hint for a question, provide the question number but no answer:
```
params = {
'question': 1,
}
```
[Complete instructions at kata.scienxlab.org](https://kata.scienxlab.org/challenge)
[An example notebook to get you started](https://gist.github.com/kwinkunks/50f11dac6ab7ff8c3e6c7b34536501a2)
----
© 2024 [Scienxlab](https://scienxlab.org/) — Code: openly licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) — Text: openly licensed under [CC BY](https://creativecommons.org/licenses/by/4.0/).