Showing posts with label Matplotlib. Show all posts
Showing posts with label Matplotlib. Show all posts

Saturday, July 5, 2025

How do you visualize glucose data from a glucose CGM report using Python?

Interpretation of data from the python code from my previous post must be exercised with caution. The program explicitly puts red dots over the curve to establish verification that the method indeed achieves its objective. We have seen that the image generated does show large red circles riding the graph. 

It is easy to show by reducing the size to 0, that the curve is traced by very tiny circles shown by an underlying red ness in the trace (zoom to see). These are shown for two the two radii assumed in the next figure.

 


However, a .CSV file is generated by the code. The graphing of this file in Microsoft Excel does not show any difference between the two cases, radius=2 and radius =0 as shown.

  


The reason is these curves (one by visualization and the other set by generated CSV file) are not using the same base.

1. The cv2.circle() visualization: This is what creates the glucose_trace_detected.jpg. 

2. The matplotlib.pyplot.plot() or scatter() visualization: This is what creates the glucose_value_mg_dL plo.

However, in the plotted graphs from CSV files we find gaps in the generated graph. They can indeed correspond to event marker positions. The red dot in the visualization is only for verifying that the entire graph is captured.

We will take a look at this possibility of getting the psotional data of events in the next post, as it gives us valuable information on event times. 


Friday, July 4, 2025

How do you extract glucose data from a glucose CGM report using Python?

 In my previous post, I described how to find the graph of glucose vs. time using a blue mask (the curve was in blue). This post is about graphing Glucose data vs. time using the curve from the previous post.

The main result of the previous post resulted in developing a mask’ for the curve as shown here.

This Python script (GlucoseCalibrated.py) that follows is designed to extract numerical glucose data from a graph image by analyzing the blue glucose trace, calibrating it to real-world glucose values, and then saving the results. The important determinations that are to be made are, 1) Correctly rendering the Y-axis of the displayed curve and establishing the Glucose data in mg/dL correctly to the numerical data from the calculation. In associating the correct Glucose values, the measurements on the curve from the report were made using GIMP. The X-axis association with time has to be done as well.

import cv2
import numpy as np
import matplotlib.pyplot as plt
import csv
import os

# --- Configuration ---

IMAGE_PATH = "LibreViewOneDayGraph.jpg"

LOWER_BLUE = np.array([100, 50, 50])
UPPER_BLUE = np.array([140, 255, 255])

# --- CRITICAL CALIBRATION PARAMETERS ---
GLUCOSE_VALUE_1 = 0
PIXEL_Y_1 = 170

GLUCOSE_VALUE_2 = 150
PIXEL_Y_2 = 107
# ----------------------------------------

print(f"Attempting to load image from: {IMAGE_PATH}. "
f"Current working directory: {os.getcwd()}")

# Load image
img = cv2.imread(IMAGE_PATH)

# Check if the image was loaded successfully
if img is None:
print(f"Error: Could not load image from {IMAGE_PATH}. "
"Please check the path and name.")
else:
print(f"Image '{IMAGE_PATH}' loaded successfully. "
f"Dimensions: {img.shape}")
img_height, img_width, _ = img.shape
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# Create mask for the blue color
mask = cv2.inRange(img_hsv, LOWER_BLUE, UPPER_BLUE)
print(f"Mask created. Number of blue pixels detected: "
f"{np.count_nonzero(mask)}")
if np.count_nonzero(mask) == 0:
print("Warning: No blue pixels found in the image with the "
"current HSV range. Check image color or HSV values.")

# Create a copy of the image to draw on (for visualization)
img_with_circles = img.copy()
circle_radius = 2

# List to store x, y coordinates and glucose values for CSV
glucose_trace_data = []
glucose_trace_data.append(
['x_pixel', 'y_pixel_raw', 'glucose_value_mg_dL'])

# --- Calculate the linear transformation parameters (m and b) ---
m_glucose_scale = (GLUCOSE_VALUE_2 - GLUCOSE_VALUE_1) / \
(PIXEL_Y_2 - PIXEL_Y_1)
b_glucose_offset = GLUCOSE_VALUE_1 - \
(m_glucose_scale * PIXEL_Y_1)

print(f"\n--- Calibration Results ---")
print(f"Using calibration points: ({PIXEL_Y_1}px -> "
f"{GLUCOSE_VALUE_1}mg/dL) and ({PIXEL_Y_2}px -> "
f"{GLUCOSE_VALUE_2}mg/dL)")
print(f"Calculated Glucose Scale (m): {m_glucose_scale:.4f}")
print(f"Calculated Glucose Offset (b): {b_glucose_offset:.4f}")
print(f"---------------------------\n")

# Iterate through each x-position to find the glucose trace
print("Starting trace detection loop...")
for x_pos in range(img_width):
column = mask[:, x_pos]
y_hits = np.where(column > 0)[0]

if len(y_hits) > 0:
y_pixel_raw = int(np.median(y_hits))

actual_glucose_value = \
(m_glucose_scale * y_pixel_raw) + b_glucose_offset
actual_glucose_value_rounded = round(actual_glucose_value, 2)

cv2.circle(img_with_circles, (x_pos, y_pixel_raw),
circle_radius, (0, 0, 255), -1)

glucose_trace_data.append(
[x_pos, y_pixel_raw, actual_glucose_value_rounded])
print(f"Trace detection loop finished. Data points collected: "
f"{len(glucose_trace_data) - 1}")

# --- Display the visualized image ---
plt.figure(figsize=(12, 7))
plt.imshow(cv2.cvtColor(img_with_circles, cv2.COLOR_BGR2RGB))
plt.title("Detected Glucose Trace on Original Image "
"(with Calibration Notes)")
plt.axis("off")
plt.show()

# Save the image with circles
output_image_filename = "glucose_trace_detected.jpg"
cv2.imwrite(output_image_filename, img_with_circles)
print(f"Visualized trace image saved to {output_image_filename}")

# --- Save data to CSV file ---
csv_filename = "glucose_trace_data_calibrated_values.csv"
try:
with open(csv_filename, 'w', newline='') as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerows(glucose_trace_data)
print(f"Glucose trace data saved to {csv_filename}")
except IOError:
print(f"Error: Could not write to {csv_filename}. "
"Please check file permissions or if the file is open.")

print("\nScript finished execution.")

Here's a step-by-step summary of its functionality:

  1. Import Libraries: It imports cv2 (OpenCV) for image processing, numpy for numerical operations, matplotlib.pyplot for displaying images, csv for writing data to CSV files, and os for path-related diagnostics.
  2. Configuration:
    • IMAGE_PATH: Specifies the path to your input glucose graph image (e.g., "LibreViewOneDayGraph.jpg"). This is the image the script will analyze.
    • LOWER_BLUE, UPPER_BLUE: These define a range in the HSV color space (Hue, Saturation, Value) that precisely represents the "blue" color of your glucose trace. Any pixels falling within this range are considered part of the trace.
  3. Critical Calibration Parameters:
    • GLUCOSE_VALUE_1, PIXEL_Y_1: These are your first calibration point. GLUCOSE_VALUE_1 is a known glucose level (e.g., 0 mg/dL), and PIXEL_Y_1 is the exact Y-pixel coordinate you manually measured from the image corresponding to that glucose level.
    • GLUCOSE_VALUE_2, PIXEL_Y_2: These are your second calibration point, representing another known glucose level (e.g., 150 mg/dL) and its corresponding Y-pixel coordinate.
    • Purpose: These two points are crucial for establishing a linear relationship between pixel Y-coordinates and actual glucose values.
  4. Image Loading and Initial Checks:
    • The script attempts to load the image specified by IMAGE_PATH.
    • It checks if the image loaded successfully. If not, it prints an error and stops.
    • It converts the image from BGR (Blue, Green, Red - OpenCV's default) to HSV (Hue, Saturation, Value) color space, as HSV is generally better for color-based segmentation.
  5. Color Masking:
    • cv2.inRange(img_hsv, LOWER_BLUE, UPPER_BLUE) creates a binary mask. This mask is a black-and-white image where white pixels represent areas of the original image that fall within the defined blue color range (i.e., your glucose trace).
    • It prints the number of detected blue pixels as a diagnostic.
  6. Calibration Calculation:
    • It calculates the m (slope) and b (y-intercept) values for a linear equation: Glucose_Value = m * raw_y_pixel + b.
    • m_glucose_scale: Represents how many mg/dL each pixel unit corresponds to. It's calculated using the two calibration points. It's typically negative because a higher pixel Y-value (further down the image) means a lower glucose value on the graph.
    • b_glucose_offset: The offset, calculated using one of the calibration points and the derived slope.
    • These values form the core of converting pixel data to meaningful glucose readings.
  7. Glucose Trace Detection Loop:
    • The script iterates through every single vertical column (x_pos) of the image, from left to right.
    • For each column, it looks at the mask to find all y_hits (white pixels, indicating blue color from the trace).
    • np.median(y_hits): If blue pixels are found in a column, it takes the median Y-coordinate of those pixels. Using the median helps to make the detection robust against noise or slight variations in line thickness.
    • Calibration Application: The y_pixel_raw (median Y-coordinate) is then fed into the linear equation (m * y_pixel_raw + b) to get the actual_glucose_value_rounded.
    • Visualization: A red circle is drawn on a copy of the original image (img_with_circles) at the (x_pos, y_pixel_raw) to visually confirm where the trace was detected.
    • Data Storage: The x_pos, y_pixel_raw, and actual_glucose_value_rounded are stored in the glucose_trace_data list.
  8. Output and Saving:
    • Display Image: The img_with_circles (original graph with red dots on the detected trace) is displayed using matplotlib.
    • Save Image: This visualized image is also saved as glucose_trace_detected.jpg.
    • Save CSV: The glucose_trace_data (containing all the detected x, y, and calibrated glucose values) is saved to a CSV file named glucose_trace_data_calibrated_values.csv.

In essence, this script automates the process of "reading" your glucose graph by color detection and translating the visual curve into a precise set of numerical data points.

Here is the result of running this code:

Attempting to load image from: LibreViewOneDayGraph.jpg. Current working directory: C:\Users\hoden\PycharmProjects\GraphtoData

Image 'LibreViewOneDayGraph.jpg' loaded successfully. Dimensions: (244, 1140, 3)

Mask created. Number of blue pixels detected: 5325


--- Calibration Results ---

Using calibration points: (170px -> 0mg/dL) and (107px -> 150mg/dL)

Calculated Glucose Scale (m): -2.3810

Calculated Glucose Offset (b): 404.7619

---------------------------

Starting trace detection loop...

Trace detection loop finished. Data points collected: 1091

Visualized trace image saved to glucose_trace_detected.jpg

Glucose trace data saved to glucose_trace_data_calibrated_values.csv

Script finished execution.

Process finished with exit code 0

The CSV file is written starting at the beginning of the curve to the end and at each point a red dot is placed on the original to unambiguosly verify that the whole curve is covered. 


Saturday, November 2, 2024

How do you visualize the histogram of an image?

A picture is worth a thousand words is always true. A one dimensional array does not make a great deal of impact but a visual will do. 

In the previous post on histograms we saw that PIL and OpenCV can be used to provide a 1-dimensional array representing the frequency of each pixel value in the image. We can use the library matplotlib to visualize this array using the following code.

---------------------------

import cv2

import matplotlib.pyplot as plt

image=cv2.imread(r'C:\Users\hoden\PycharmProjects\exploreImage\Images_3\white.png')

histogram = cv2.calcHist([image], [0], None, [256], [0, 256])


# Plot the histogram

plt.plot(histogram)

plt.title('Histogram of an all-white image')

plt.xlabel('Pixel Intensity')

plt.ylabel('Frequency')

plt.show()

------------------------

When we run this code in PyCharm, the a graphic of the Histogram will be displayed. Here is the result of running the above code twice in PyCharm. Matplotlib is pretty flexible and allows us to illustrate the plots with labels.







Monday, October 28, 2024

How do you install matplotlib for python?

 

We have seen earlier how to install PIL and OpenCV to visualize images. Matplotlib is yet another library for creating complex plots and graphs.

 Each of these graphic libraries have their own application area:

PIL(Pillow): Great for simple manipulations like cropping, resizing and adding filters. Easy to use but not for extensive visualizations.

OpenCV: Great for real-time computer vision tasks and image processing and lend itself to feature detection, object recognition and video analysis.

Matplotlib: Great for complex plots, graphs,  and charts. Highly customizable.


Installing Matplotlib

Herein, I consider installing matplotlib in the PyCharm IDE that was used for PIL and OpenCV. You can use either the python interpreter to install the library package or the virtual terminal.

In the PyCharm IDE locate the Packages icon highlighted in blue. You can see other packages from earlier installs like pip, pillow, etc. 


In the search box type 'matplotlib' and click Install on the right


There was an error that indicated it is being used. However, it is not installed on this machine in any other program. If this works for you you are in luck.


The virtual terminal is another way to install packages. Locate the Terminal icon in PyCharm. The command line is displayed on the right. 


Type in the following : pip install matplotlib

This should install matplotlib. The program came back saying that it is already present in the site packages. 

------------

(.venv) C:\Users\hoden\OneDrive\Desktop\PyCharm\PIL>pip install matplotlib

Requirement already satisfied: matplotlib in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (3.9.2)Requirement already satisfied: contourpy>=1.0.1 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (1.3.0)Requirement already satisfied: cycler>=0.10 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (0.12.1)Requirement already satisfied: fonttools>=4.22.0 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (4.54.1)Requirement already satisfied: kiwisolver>=1.3.1 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (1.4.7)Requirement already satisfied: numpy>=1.23 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (2.1.1)Requirement already satisfied: packaging>=20.0 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (24.1)Requirement already satisfied: pillow>=8 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (10.4.0)Requirement already satisfied: pyparsing>=2.3.1 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (3.2.0)Requirement already satisfied: python-dateutil>=2.7 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from matplotlib) (2.9.0.post0)  Requirement already satisfied: six>=1.5 in c:\users\hoden\pycharmprojects\exploreimage\.venv\lib\site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)[notice] A new release of pip is available: 23.2.1 -> 24.3.1[notice] To update, run: C:\Users\hoden\PycharmProjects\exploreImage\.venv\Scripts\python.exe -m pip install --upgrade pi

And, indeed it was. The reason for this is perhaps the project files are not in the virtual environment. 

Anyway, before you use matplotlib in your python project, you need to import the plotting routine using 

Import matplotlib.pyplot as plt

Usage of matplotlib 

Python code for displaying an image. 

We will use the same RGB.png image as in the earlier posts.

----------------

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

# Load the image
image = mpimg.imread(r'C:\Users\hoden\PycharmProjects\exploreImage\Images_2\RGB.png')
# Display the image
plt.imshow(image)
plt.axis('off')
# Hide axes for a cleaner look
plt.title('Displayed Image')
plt.show()

----------------

The following image gets displayed:


What display device matplotlib uses to display an image?

Matplotlib uses a backend to display images and plots. The backend is responsible for rendering the visualizations to the screen or saving them to a file. By default, Matplotlib selects the appropriate backend based on your environment. Some common backends are:

  • TkAgg: Uses the Tkinter library for rendering.

  • Qt5Agg: Uses the Qt5 library for rendering.

  • MacOSX: Used for rendering on macOS.

  • GTK3Agg: Uses the GTK3 library for rendering.

  • Agg: Used for rendering to files without displaying on screen.

How to check the display device used for rendering:

The following code is used to check the display device:

Import matplotlib
print(matplotlib.get_backend())

On my Windows 11 laptop, it appears to use the TkAgg library for rendering as I get a reply 'tkagg' for the above code.





Sunday, April 28, 2024

How easy is it to work with image recognition using PyCharm Community edition?

 

PyCharm Community edition is a very powerful IDE for developing Python applications. Community editions while free lack all the features of a professional edition. 

PyCharm has many desirable features:

1. Supports image processing libraries such as PIL(Pillow), OpenCV and matplotlib. These libraries can be installed from within PyCharm using pip.

2. You can easily create Python files(.py)

   PIL after installing can be used to work with images(Load, manipulate and save)

   Image manipulation allows loading, resizing, filtering and saving of images

3. It has a Python Console for quickly running and testing experimental codes. Console also supports         displaying images directly in the console.

4. PyCharm allows youto format Python code consistently and has built-in refactoring tools that help in        maintaining code and improving readability.

5. PyCharm's virtual environments can isolate image processing project from other Python projects.

6. For image recognition, you will require other deep learning libraries such as Keras and TensorFLow.

   For image classification you can build and train custom conventional neural networks(CNNs)

   For feature extraction and preprocessing you can use PIL and OpenCV before feeding into neural 

   network

   Extend image recognition to object detection within an image

   You can visualize model performance, loss curves and accuracy metrics using matplotlib

   OpenCV and ImageViewer plugins allow for efficient image manipulation and analysis.

This should take you quite bit into the image processing tasks

How do you install PyCharm Community Edition?

Just follow the link.


Run the executable file preferably as the administrator. The PyCharm will be installed pretty quickly.




Sunday, March 18, 2018

What is SciPy?

SciPy is a Python-based open-source software for science and engineering from SciPy.org.

These are the contents of the core package


Scipy_0

NumpPy 1.14.2 released 2018-03-12

Get the above here:
https://www.scipy.org/scipylib/download.html

NumPy is a basic N-dimensional array package

It has among others:
  • a powerful N-dimensional array object
  • sophisticated (broadcasting) functions
  • tools for integrating C/C++ and Fortran code 
  • useful linear algebra, Fourier transform, and random number capabilities
It is also an efficient multi-dimensional container for data with arbitrary data types. It is licensed under BSD.

Read more here:
https://docs.scipy.org/doc/
SciPy libarary Scientic computing