Beispiel #1
0
/**
 * cd_spectrum_planckian_new_full:
 * @temperature: the temperature in Kelvin
 * @start: the new spectrum start
 * @end: the new spectrum end
 * @resolution: the resolution to use when resampling
 *
 * Allocates a Planckian spectrum at a specific temperature.
 *
 * Return value: A newly allocated #CdSpectrum object
 *
 * Since: 1.3.1
 **/
CdSpectrum *
cd_spectrum_planckian_new_full (gdouble temperature,
				gdouble start,
				gdouble end,
				gdouble resolution)
{
	CdSpectrum *s = NULL;
	const gdouble c1 = 3.74183e-16;	/* 2pi * h * c^2 */
	const gdouble c2 = 1.4388e-2;	/* h * c / k */
	gdouble wl;
	gdouble norm;
	gdouble tmp;
	guint i;

	/* sanity check */
	if (temperature < 1.0 || temperature > 1e6)
		return NULL;

	/* create spectrum with 1nm resolution */
	s = cd_spectrum_sized_new (531);
	s->id = g_strdup_printf ("Planckian@%.0fK", temperature);
	cd_spectrum_set_start (s, start);
	cd_spectrum_set_end (s, end);

	/* see http://www.create.uwe.ac.uk/ardtalks/Schanda_paper.pdf, page 42 */
	wl = 560 * 1e-9;
	norm = 0.01 * (c1 * pow (wl, -5.0)) / (exp (c2 / (wl * temperature)) - 1.0);
	for (i = 0; i < s->reserved_size; i++) {
		wl = cd_spectrum_get_wavelength (s, i) * 1e-9;
		tmp = (c1 * pow (wl, -5.0)) / (exp (c2 / (wl * temperature)) - 1.0);
		cd_spectrum_add_value (s, tmp / norm);
	}
	return s;
}
Beispiel #2
0
/**
 * osp_device_take_spectrum_internal:
 **/
static CdSpectrum *
osp_device_take_spectrum_internal (GUsbDevice *device,
				   guint64 sample_duration,
				   GError **error)
{
	CdSpectrum *sp;
	gdouble val;
	gsize data_len;
	guint i;
	g_autofree guint8 *data = NULL;
	g_autoptr(GTimer) t = NULL;

	/* set integral time in us */
	if (!osp_device_send_command (device, OSP_CMD_SET_INTEGRATION_TIME,
				      (guint8 *) &sample_duration, 4, error))
		return NULL;

	/* get spectrum */
	t = g_timer_new ();
	if (!osp_device_query (device, OSP_CMD_GET_AND_SEND_RAW_SPECTRUM,
			       NULL, 0, &data, &data_len, error))
		return NULL;
	g_debug ("For integration of %.0fms, sensor took %.0fms",
		 sample_duration / 1000.f, g_timer_elapsed (t, NULL) * 1000.f);

	/* check values */
	if (data_len != 2048) {
		g_set_error (error,
			     OSP_DEVICE_ERROR,
			     OSP_DEVICE_ERROR_INTERNAL,
			     "Expected %i bytes, got %" G_GSIZE_FORMAT,
			     2048, data_len);
		return NULL;
	}

	/* export */
	sp = cd_spectrum_sized_new (1024);
	for (i = 0; i < 1024; i++) {
		val = data[i*2+1] * 256 + data[i*2+0];
		cd_spectrum_add_value (sp, val / (gdouble) 0xffff);
	}

	/* the maximum value the hardware can return is 0x3fff */
	val = cd_spectrum_get_value_max (sp);
	if (val > 0.25) {
		g_set_error (error,
			     OSP_DEVICE_ERROR,
			     OSP_DEVICE_ERROR_INTERNAL,
			     "spectral max should be <= 0.25f, was %f",
			     val);
		cd_spectrum_free (sp);
		return NULL;
	}

	return sp;
}
Beispiel #3
0
/**
 * cd_spectrum_subtract:
 * @s1: a #CdSpectrum instance, e.g. a sample
 * @s2: a #CdSpectrum instance, e.g. a dark calibration
 * @resolution: the resolution to use when resampling
 *
 * Subtracts one spectral plot from another. If the spectra have the same start,
 * end and the same number of data points they are not resampled.
 *
 * Return value: a #CdSpectrum instance
 *
 * Since: 1.3.1
 **/
CdSpectrum *
cd_spectrum_subtract (CdSpectrum *s1, CdSpectrum *s2, gdouble resolution)
{
	CdSpectrum *s;
	gdouble max;
	gdouble min;
	gdouble nm;
	guint i;

	g_return_val_if_fail (s1 != NULL, NULL);
	g_return_val_if_fail (s2 != NULL, NULL);

	/* we can do this without resampling */
	if (fabs (s1->start - s2->start) < 0.01f &&
	    fabs (s1->end - s2->end) < 0.01f &&
	    s1->data->len == s2->data->len) {
		s = cd_spectrum_sized_new (s1->data->len);
		s->id = g_strdup_printf ("%s-%s", s1->id, s2->id);
		s->start = s1->start;
		s->end = s1->end;
		for (i = 0; i < 3; i++)
			s->wavelength_cal[i] = s1->wavelength_cal[i];
		for (i = 0; i < s1->data->len; i++) {
			gdouble tmp;
			tmp = cd_spectrum_get_value (s1, i) - cd_spectrum_get_value (s2, i);
			cd_spectrum_add_value (s, tmp);
		}
		return s;
	}

	/* resample */
	min = MIN (cd_spectrum_get_start (s1), cd_spectrum_get_start (s2));
	max = MAX (cd_spectrum_get_end (s1), cd_spectrum_get_end (s2));
	s = cd_spectrum_new ();
	s->id = g_strdup_printf ("%s-%s", s1->id, s2->id);
	s->start = min;
	s->end = max;
	for (nm = min; nm <= max; nm += resolution) {
		gdouble tmp;
		tmp = cd_spectrum_get_value_for_nm (s1, nm) -
			cd_spectrum_get_value_for_nm (s2, nm);
		cd_spectrum_add_value (s, tmp);
	}
	return s;
}