giovedì 3 maggio 2018

SVG arc path explained drawing circular sectors

I found quite hard to understand how svg arc path works. In the W3 docs is not explained well, and even though there are some attempts to explain them in other major sites e.g. MozillaO'Relly Common wiki and a StackOverflow question maybe the clearest was this one by Pindari but still, I could find an easy image to understand what change what. In this tutorial, I will focus on drawing circular sectors.

The elliptical arc curve commands for drawing circular sectors

The elliptical arc curve is denoted by the capital "A" using the absolute reference system and the lower case "a" for using a relative reference system. Let's start using an absolute reference system.

The W3 definition of the parameters is the following: 

A rx ry x-axis-rotation large-arc-flag sweep-flag xf yf

We create  500 x 500 svg sand box:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
<svg width="5cm" height="5cm" viewBox="0 0 500 500"
xmlns="" version="1.1">
<title>Undrestanding ARC svg</title>
<desc>Simple absolute arc</desc>
<!-- here will go the code -->

From now on all the code reported is supposed to be inside the svg tag. If you want to test it online without creating files on your PC you can use this applet (press the magnifying glass for running the code).

1.1 The simplest semi-circle

  1. We centre the object moving it at the coordinate 250,250 using the command M 250 250 (these are the starting coordinates of our arc!). 
  2.  If we want a semi-circle the radius will be the same for ry and rx, we set it to 100 (NOTE: the radius is always relative of course). 
  3. If we started a 250,250 and we have a radius of 100 hence a diameter of 200 the end point of our semicircle will be 450,250 as shown in the figure.
  4. Finally, we will close the path using "Z" command.
This is the code that you need:

<g stroke="none" fill="lime">
<path d="
M 250 250
A 100 100 0 0 0 450 250

And here the results labelled with all the parameters.

Behind the scene, the centre "c" will be computed from the starting point from the previous command (M) and the xf,yf of the "A" command.

1.2 The bottom left quarter of a circle

Now making a quarter of a circle seems easy, we keep the same starting point it will end at x 350 and y 350. But if we change only these parameters the results will be a circular segment (see next figure a).
So we need to add a line with the command "L" that connects the final point xf,yf to the centre of the circle (xc = 350, yc = 250).

<g stroke="none" fill="lime">
<path d="
M 250 250
A 100 100 0 0 0 350 350
L 350 250

The figure b seems promising. 

1.3 The bottom right quarter of a circle

For making the bottom right quarter of circle we have to change the starting point:
Setting  M to 350 350 and A to 100 100 0 0 0 450 250 will do the trick. We can also invert the starting and ending coordinate and then use the sweep_flag to obtain the same results: 
M 450 250       
A 100 100 0 0 1 350 350
                        ^ Sweep_flag
In our cases maybe is more easy to just change the starting and ending points.

1.4 Drawing sectors larger than 180°

Let's come back to our original semi-circle when we try to draw sectors lareger than 180° we experience some problems fig a.
<g stroke="none" fill="lime">
<path d="
M 250 250
A 100 100 0 0 0 350 150

We can actually notice that there are two arcs with the same radius, starting point and ending point that can be described (Figure below). One bigger (b) and one smaller (a) it's not intuitive but they have the same radius just the centre is different! Maybe it's time to use the large-arc-flag to select the larger. Changing A to 100 100 0 1 0 350 150  and adding as usual L 350 250 will fix this issue.

1.5 All the others sectors

We covered most of the cases with sectors varying of 90° or pi/2. We understood that arc function is using a cartesian reference system not a polar one, so we have always to specify the starting and ending point of the arc. But what if  I want to describe a circular sector from 22° to 78° with radius 42 and centred at 67,85? We can try to find a method to get the output using these three simple inputs. I will use Python for this task starting using the values already tested.

x_center = 350
y_center = 250
r = 100

From math classes, we remember that conventionally the position 0° is on the right part of the circle. So if we want to draw a sector starting from 0° going to 180° the starting position will be x_center + radius and the ending point x_center - radius. ( The simples semicircle example with end-start positions inverted). 
If the end angle is 45° the x position will be x_center + r*cos(45°) and y y_center. While if the end angle is 90° the y position will be y_center - r*sin(90°). We need the minus sign because the to left corner is the origin of our reference system in a svg file! The same holds true for the start angle.
So using numpy given any start and end angle the inputs for the arc function can be calculated like this:

import numpy as np 
startangle = 5
endangle = 125
radiansconversion = np.pi/180.
xstartpoint = xcenter + r*np.cos(startangle*radiansconversion)
ystartpoint = ycenter - r*np.sin(startangle*radiansconversion)
xendpoint = xcenter + r*np.cos(endangle*radiansconversion)
yendpoint = ycenter - r*np.sin(endangle*radiansconversion)
large_arc_flag = 0

Numpy trigonometric functions use radians so we have to convert the angles in radians using a factor.
Now we have to deal with the problem described in §1.4 that can be solved with simple an if statement:

if endangle - startangle > 180: large_arc_flag = 1

1.6 An exception: the circle

This method works well for every angle where start angle is less than end angle and the difference is less than 360°. There are some workarounds to create circles using arcs but the best thing to d, in my opinion,n is to create directly a circle. 

1.7 Wrapping all up in a function

We can wrap up all our efforts in a Python function which will append to an .svg file the code:

def write_svgarc(xcenter,ycenter,r,startangle,endangle,output='arc.svg'):
    if startangle > endangle:
        raise ValueError("startangle must be smaller than endangle")
    if endangle - startangle < 360:
        large_arc_flag = 0
        radiansconversion = np.pi/180.
        xstartpoint = xcenter + r*np.cos(startangle*radiansconversion)
        ystartpoint = ycenter - r*np.sin(startangle*radiansconversion)
        xendpoint = xcenter + r*np.cos(endangle*radiansconversion)
        yendpoint = ycenter - r*np.sin(endangle*radiansconversion)

        if endangle - startangle > 180: large_arc_flag = 1
        with open(output,'a') as f:
            f.write(r""" <path d=" """)
            f.write("M %s %s" %(xstartpoint,ystartpoint))
            f.write("A %s %s 0 %s 0 %s %s"
            f.write("L %s %s" %(xcenter,ycenter))
            f.write(r""" Z"/> """ )
        with open(output,'a') as f:
            f.write(r"""<circle cx="%s" cy="%s" r="%s"/>"""

Remember to put everything inside a proper svg environment!

martedì 1 luglio 2014

Scanning transmittance NIR imaging system using LEDs matrix and Python.

NIR transmittance imaging is a techniques used in cultural heritage diagnostic. Similarly to reflectography, NIR transmittance imaging used a NIR source and a sensor able to detects these wavelengths. However in NIR transmittance imaging the painting is between the NIR source and the detector.  Normally a Halogen lamp is used but this has several disadvantages:

  • Warms the painting. 
  • Some light is reflected and diffused from the surrounding objects, and so is quite difficult to obtain a pure transmittance image.
  • Not so easy to handle.
Using a little LED matrix can resolve all this problems adding further advantages:

  • LEDs produce narrow light spectra, so generally you don't need a IR-PASS filter in your camera, this means that theoretically you could generally achieve a better MTF.
  • There are available different type of IR LEDs operating in different NIR region (940 nm, 850 nm etc. etc.) so basically you can build cheaply a multispectral imaging system. Or even multispectral polarized imaging system... 
There is only a big problem: how can you analyze a large surface using a little LEDs lamp? I have tried to solve it using a simple algorithm.

NIR transmittance imaging using a little NIR LEDs  matrix  at 940 nm .

Suppose you are in a completely dark room recording a video, the painting appear black in the area where is not lighted, moving the lamp when a different area is lighted the pixel values increase. So when you scan the painting surface with your lamp, keeping your lamp at a fixed distance basically what you need is to substitute the unlighted with the lighted ones. So the algorithm compare the same pixel and keep the highest value. You can compare the same pixel of an acquisition with the next acquisition or you can set a threshold (something like: if pixel>background and pixel < 255: result_pixel=pixel). The first solution is quite simple to achieve using Python, keeping all the snapshot in a folder you can use this script:
from PIL import Image,ImageChops
from os import listdir,sep
def FolderElab():
    for i in folder:
    return fused 

I've used an old 0.31MP webcam after removing the ICF and substituting it with a piece of floppydisk (as mentioned earlier you can use it without an IR-PASS filter, however sometimes could be easier install one to operate in lit rooms). This is the first result, merging all the images.

Resulting image made of different images as the previous one.

Python script to collect LEDs matrix data.

Analyzing a LEDs matrix one LED by one reporting data in a spreadsheet and then analyzing it could be very time consuming. A simple python script can speed up a little bit the tests, organizing the data and plotting the result. The resulting image, automatically generated using matplotlib, show the mean and the standard deviation for every LED and resistance in the circuit. You can specify the number of rows and columns depending on your matrix.

Code is hosted on gitHub.

giovedì 26 giugno 2014

DYE LEDs brightness tester.

To reach an homogeneous output an accurate calibration is needed. Same LEDs can have different brightness so is important to find if there are LEDs brighter than others and substitute them. LEDs brightness is usually measured with a spectro-radiometer and an integrating sphere this allows very accurate, absolute and quantitative measurements. In our case we don't care about an absolute value in $W/m^{2}$ or in LUX we simply want to know if a LED is brighter than another. This seems a easy task to perform with a simple camera: measuring pixels values, but in fact it isn't because in a breadboard (when you usually make the prototype of your lamp) little variation of the LED inclination cause huge differences in light output. One possible solution is to use another LEDs as a photodiode and measure the voltage or the amps generated by the source LED. This instrument is quite easy to build, I've used a plastic wine's bottle cap to imbed securely the "probe LED". The "probe LED" is inserted in a narrower side of the parallelepiped, a larger diameter in the other side allows an easy removing of the LED from the probe, when the source LED is inserted in the other side.
Simple LED brightness tester Leds 3d models by LED signal light user
It is simpler to design the probe so that the source LED touches the probe LED when you are measuring. In this way you are sure that the distance is every time the same. We will see in the next post how to collect the data of many LEDs effectively.

martedì 17 giugno 2014

IR LED lamp design

LEDs have many advantages over traditional lighting, in multi-spectral imaging the main advantage is that they have a narrow well-know output spectrum. Using a small source allows a better control over it, reducing Stray light.
Design a LED lamps is not easy as it seems. In radiometric experiments power consumption is not a problem but homogeneous output and stability (stable irradiance and spectral band) are fundamental parameters to deal with. Spectral output depends on temperature in my case I had $\lambda_{p} $ of 0.2 nm/K so if the temperature rise to 20 K you have a 4 nm shift. To get some more infos I asked a question on electronics.stackexchange.

Parallels or series?

The first thing you need to know is that not all the LEDs are equal, some of them are brighter some dimmer, so you should search for binned LED to start with the optimal condition from the beginning. The second problem is to find the best arrangement for the LEDs. If you google a little bit you will find a lot of video showing how to build LEDs matrix or lamps. The most common advice is to put one resistance for every LEDs, this reduce problems related to the difference between the LEDs. However this arrangement also required a large amount of power and so produce a large amount of heat so I prefer to find another solution for a prototype. You can place LEDs in series (second arrangement in the figure) this lead to a more efficient arrangement but it has some disadvantages too. We will see them in the next part.
The two antipodes full-parallel and full-series arrangements of six LEDs.

Calculating resistance value

If you have choose a LEDs and a source the only thing that you have to calculate are the resistances shown in figure. It is very easy, you should think that you are forced to distribute ALL your energy (V) to your components. There are components like LEDs that can't take too much energy so you have to add another component that take this surplus: resistor. So if you have to distribute 12 V and the LEDs can take only 9 V you have to find a resistor that take 3 V, keeping the current fixed to a value that doesn't destroy the LEDs , indicated as $I_{f} $ . $$ R= \frac{Supply~Voltage-(LED_{V} \times n_{LEDs})}{Current}$$.
Whit a DC supply of 12 V if the LED voltage drop (indicated as $ V_{f} $) is 1.35 V and the $ I_{f} $ is equal to 100 mA you have for the first arrangement :$$\frac{12-(1.35 \times1)}{0.1}=106 \Omega$$ for the second: $$\frac{12-(1.35 \times 6)}{0.1}=39 \Omega$$. It seems that the second arrangement is better but if we think that the voltage can fluctuate we can see that using a higher resistance can lead to a more stable output. This is is easy to see from the next graph that is a simple plotting of the Ohm law: $$i=\frac{V}{R}$$.
Response to voltage fluctuation of the two arrangements.
You can see that when you have a small resistor (e.g. 39 Ohm) a small voltage fluctuation cause a larger current flow fluctuation hence a larger variation in LED irradiance. Of course maybe is better to stabilize the voltage before and use the second arrangement where all the LEDs share the same current flow.

lunedì 16 giugno 2014

Python Gimp plugin to compare multi-spectral imaging images

When you have many images of the same subjects in different spectral bands some times you want to compare them. In this case the simple things to do is to juxtapose them showing local differences with a marker (an arrow or a circle) that indicates what is visible in one spectral band and not in the other. That's could be a quite tedious process, I have developed a Python Gimp plug-in to perform this task quickly. Basically you can load the images as different layers and juxtapose them. Furthermore you can add a transparent layer that can be duplicated over the others layer, so you can put in it markers that will be automatically superimposed over the same area in the others layer.  This video shows how it works.

Plugi-in are hosted on GitHub

giovedì 5 giugno 2014

Analyzing and reporting spectra: Python to LaTeX Raman spectra analyzer

Most of the chemists don't know much about programming indeed mathematicians, physicists and of course IT engineers are familiar with Python and LaTeX and so they already know about their great potential. Analytical chemists use Excel (or software design for them like OriginPro) and Word processors, these are indeed great tools for data analysis but sometimes are not so efficient and convenient for repeated tasks. In academia these tools are very common (just look at some academic posters to recognize who uses Excel or OriginPro) and so they teach you to use them thinking that you will analyze only o bunch of spectra for the publication and then you will move to another project and another instrument. In industry many times you begin your career with an instrument and you finish it with him, so reduce time to analyze and report his spectrum is a great advantage. LIS (LIMS) are normally used to organize better data, but indeed sometimes we only need something between these two antipodes, I will show you my workflow using Python and LaTeX for analyzing and reporting Raman spectra in in this post. I begin to deal with spectra when I was a Raman spectroscopist this was a typical spectrum saved as .csv I used to work with:
How my spectra looked like

I needed only the DATA to plot them so I have to avoid other things like parameters and additional informations. I learnt how to create a filter with Origin to skip the first rows but, how can I avoid to import the peaks found by the spectrometer's software? This was a more difficult task for Origin, even the peaks analyzer was a very slow process. Then when I finally insert the image in the Word file I used to found errors and so I had to repeat the whole process! So I begin to develop my own tools to analyze the spectra (found peaks...) and report them directly in TeX. I posted my work in GitHub basically it consists in a general python script to analyze peaks in Raman spectra (positive peaks) and the filter to import spectra form Xantus-1 spectrometer as an example of how everyone can make his own filter to import their own spectra. When you obtain the matplotlib image you can save it but I think that exporting it as LaTeX code is more interesting and lead to many advantages. These are some of the advantages in using the whole methods:
  • Very fast importing methods
  • Print a pice of TeX code that lead to images with publication resolution and all the advantages of LaTeX.
  • If you need you can edit the LaTeX code and so the image directly in a second step.
  • You can add directly into the caption the acquisition parameters for every spectrum, extracting them directly from the spectrum file.
This video shows how it works: