How to calculate the colour a human eye sees when looking at a light spectrum? I have to do a presentation about colourants in Chemistry class (grade 12, advanced) and want to write a program that calculates and visualizes the colours of some simple molecules.  
What I need is a formula to calculate the visible colour (e.g. RGB-values of the colour that would look the same like the given spectrum).
Should be able to handle both monochromatic spectral lines and wide spectres. (e.g. with integrals or something like that?)
 A: Trying to break my bad habit of answering in comments, putting my previous stuff down here now. As I said, I'm largely drawing on a blog post I did a couple years ago, working out the color of the sky. I had a spectrum, and I wanted a color. As I mentioned above, you can't just take a spectrum and output an equivalent wavelength--only some colors are so called "spectral" colors. These are the ones in the rainbow. 
To get a color from a spectrum, we need to know how the eyes respond to the incoming light. You have three kinds of cells, as you know, with different regions of sensitivity. Let's say we have a function $f_i(\omega)$ that characterizes the response to a frequency $\omega$, with 1 being the maximum and 0 being the minimum. The spectrum intensity is given by $I(\omega)$. Then we can talk about the total response:
$$
R_i = \frac{\int_0^\infty \mathrm{d} \omega \ f_i(\omega) I(\omega)}{\int_0^\infty \mathrm{d} \omega \ f_i(\omega)}
$$
I've normalized it such that a flat spectrum gives you 1. You can see here that there are two ways to get a large response: either have some intensity at a place where the response $f$ is strong, or a lot of intensity in a place where it isn't. Now, the subscript is because there will be three of these: $R_1, R_2, R_3$, one for each cell. You can now take those responses (which are roughly corresponding to red, blue, and green, but not really) and run it through a matrix that transforms it into the computer-image RGB basis. Now, the computer defines colors there's actually a fourth, brightness parameter. To get this from a spectrum you'd need to know the actual measured intensity as well as a lot more about how the eye responds, but with the RGB value you can get a range of colors that corresponds to what the spectrum might look like.
Now, you specifically asked about how one would get this from a series of spectral lines. The answer here is that the spectrum is zero in most places, but very strong in others. In this case the mathematical structure you want would be called Dirac delta functions, but we can be a little simpler. Basically, the integral will now become a sum over all the discrete spectral lines:
$$
R_i = \frac{\sum_{j} \ f_i(\omega_j) I(\omega_j)}{\int_0^\infty \mathrm{d} \omega \ f_i(\omega)}
$$
Here we're now summing over every line that's present (labeled $j$), and just getting that one value out of what was previously the integral, but still normalized the same way. You could now use the intensity function to adjust the strength of the various spectral lines. Once you have the response values you proceed exactly as in the continuous case.
A: You will not be able to get the proper color of the narrow bands because they fall outside of the RGB gamut. However you can get their correct hue.
You need color matching functions (usually we use 1931 2° CMFs from the CIE, check online... or here under CMFs category http://www.cvrl.org/)
CMFs multiplied by your spectrum, then summed, will give you the proprtions of primaries X, Y, Z that match the color for a human observer.
Once you have this, you can scale your results and convert from XYZ to sRGB for example (or any other RGB system you'd like), the conversion is explained there:
XYZ2sRGB 
To properly scale your XYZ values, I advice you to get a "white reading" using only solvent for your spectrophotometer. The Y value of this reading will be your white reference for scaling the other XYZ values.
In order to get good hues for the narrow bands falling outside sRGB gamut, you can convert to CIE LCH and reduce C* until you fall inside RGB gamut.
See here: XYZ2LAB >> LAB2LCH 
XYZ 2 LCH
