/** * 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; }
/** * 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; }
/** * 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; }