Multi-channel support- Week 10 to 12

Tarun Jain
4 min readSep 4, 2023

--

In this article, I will share my progress done in Google Summer of Code 2023 at caMicroscope from Week 10 to Week 12.

User-based channel selection

For the input image, rather than directly passing it to the algorithm, the mentor wanted to make changes in this step. Once the user uploads the input image, he should always be given a choice to select R/G/B for each channel in that input image.

@app.route("/<filename>")
def main(filename):
image_file = f"./{filename}"

if image_file.split('.')[-1] not in ALLOWED_EXTENSIONS:
flash("Invalid Image file")
else:
if image_file.endswith(".mat"):
band = sio.loadmat(image_file)
arr = band['hsi']
num_channels = arr.shape[2]
else:
img_tif = Image.open(image_file)
num_channels = len(img_tif.getbands())+2
channel_labels = [f"Channel-{i}:" for i in range(num_channels)] #send total channels as alphabets

#return jsonify({"filename": image_file, "channels": channel_labels})
return render_template('channels.html', filename=image_file, channels=channel_labels)

Once the user selects the required channels, we send the order of the selected channel in the list. And convert the input image into RGB according to that order.

@app.route('/process_channels', methods=['POST'])
def process_channels():
filename = request.form['filename']
num_channels = int(len(request.form) - 1) # Subtract 1 for the filename field
channel_order = [int(request.form[f'channel_{i}']) for i in range(num_channels)]

return redirect(url_for('view_image', filename=filename, channel_order=channel_order))

This completes this part, where we allow the user to pick the RGB for the specific channel.

Docker compose

caMicroscope codebase contains a repository named “Distro” that contains the docker-compose .yml file with the containers for different features. To integrate a Docker compose for the multi-channel we first need DockerFile for the existing Python Flask code.

I pushed my complete code on GitHub: https://github.com/lucifertrj/GSoC23_multi_channel

Dockerfile

FROM python:3.10

ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0

WORKDIR /app
RUN apt-get update && apt-get install -y libvips42
COPY requirements.txt /app/
RUN pip install -r requirements.txt
COPY . /app/
EXPOSE 5000

CMD ["flask", "run"]

Once the Dockerfile is working and tested we update the docker-compose develop.yml file in Distro.

multichannel:
build: "https://github.com/lucifertrj/GSoC23_multi_channel.git#main"
container_name: ca-multi
restart: unless-stopped
volumes:
- ./images/:/images/

Running the application

Once all the update in Dockerfile and develop.yml is completed. Open the Distro in the terminal or CMD and run the following command to build the Docker image.

docker-compose -f develop.yml build

Once the Docker build is completed, we are up to running the application on the local host. In order to do that stay in the Distro directory and run the following command:

docker-compose -f develop.yml up

Now open the localhost:4010 and enter the URL as given in the caption of the image.

http://localhost:4010/multichannel/

Once the user picks the sample image, he is re-directed to where he can choose the channels to convert into RGB. This can be picked in any order.

http://localhost:4010/multichannel/44153.tif

After choosing the R/G/B choice, click on View Image to visualize the OpenSeaDragon and DZI form of the converted image.

http://localhost:4010/multichannel/viewer/44153.tif?channel_order=0&channel_order=2&channel_order=0

Now, we enter the final phase of the GSoC project. That is implementing the entire application on the caMicroscope codebase.

Integrating with caMicroscope codebase

The application that I built so far is Pure Python code and all the route redirects happen using the url_for function. Now I need to convert all the url_for path into the relative path for Docker compose to run. The next challenge is that caMicroscope is pure JavaScript and doesn’t support Python. Since the URL or path for the Python approach can be fetched from docker-compose with path: “../../multichannel”.

document.getElementById('chooseButton').addEventListener('click', fetchData);

async function fetchData() {
try {
console.log("hello");
const response = await fetch("../../multichannel/", {
method: "GET",
});
if (response.ok) {
const data = await response.json();
console.log("Route, direct Working...");
console.log(data);
}
} catch (error) {
console.log("Error:", error);
}
}

The above code is too just check if I am able to get the response on the browser console. It worked and I was able to get the results.

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../../core/openseadragon/openseadragon.js"></script>
<link rel="stylesheet" href="./style.css">
<title>Multi channel image support</title>
</head>
<body>
<button id="chooseButton">Choose</button> <!-- Replace "Check" with a button -->
<div id="pages"></div>
<div id="workspace" class="flex-grid"></div>
</body>
<script src="./multichannel.js"></script>
</html>

--

--

Tarun Jain

Youtube: AIWithTarun || ML @AIPlanet || GSoC'24 RedHen Lab ||GSoC'23 @caMicroscope || GDE in ML