def is_reference(self, spectrum): refls = spectrum.reflectances #if a reflectance is greater than 1.0 then it is a reference if np.max(refls) > 1.0: return True if self._context == 'gveg': #check the total range of reflectances if np.ptp(refls) < self._req_reflectance_range: return True #check presence of minima in specified wavelength ranges waves = spectrum.wavelengths for (win, rad) in zip(self._minima_wins, self._minima_radii): lt_idx = closest_array_index(win[0], waves) rt_idx = closest_array_index(win[1], waves) minima_found = False for i in range(lt_idx, rt_idx): cval = refls[i] li = max(i - rad, 0) ri = min(i + rad, len(refls)) if np.all(np.greater_equal(refls[li:ri], cval)): minima_found = True if not minima_found: return True return False
def wavelength_subset(self, wavestart, wavestop): idx1 = closest_array_index(wavestart, self.wavelengths) idx2 = closest_array_index(wavestop, self.wavelengths) + 1 return Spectrum(data = self._data[idx1:idx2, :], idstr = self._idstr, company = self._company, instrument = self._instrument)
def is_green_vegetation(self, spectrum): self._ndvi, self._reflectance_range = 0.0, 0.0 waves = spectrum.wavelengths refls = spectrum.reflectances #perform the ndvi based test nir_start = closest_array_index(self._ndvi_nir_range[0], waves) nir_end = closest_array_index(self._ndvi_nir_range[1], waves) red_start = closest_array_index(self._ndvi_red_range[0], waves) red_end = closest_array_index(self._ndvi_red_range[1], waves) nir_mean = np.mean(refls[nir_start:nir_end]) red_mean = np.mean(refls[red_start:red_end]) self._ndvi = (nir_mean - red_mean)/(nir_mean + red_mean) if self._ndvi < self._ndvi_thresh: return (False, self._ndvi, self._reflectance_range) #perform reflectance range based test #consider the middle 90% of wavelengths chop_size = np.size(refls)*5/100 + 1 start = chop_size stop = np.size(refls) - chop_size self._reflectance_range = np.ptp(refls[start:stop]) if self._reflectance_range < self._reflectance_range_thresh: return (False, self._ndvi, self._reflectance_range) #it is green vegetation if this point is reached return (True, self._ndvi, self._reflectance_range)
def wavelength_subset(self, wavestart, wavestop): idx1 = closest_array_index(wavestart, self.wavelengths) idx2 = closest_array_index(wavestop, self.wavelengths) + 1 return Spectrum(data=self._data[idx1:idx2, :], idstr=self._idstr, company=self._company, instrument=self._instrument)
def is_green_vegetation(self, spectrum): self._ndvi, self._reflectance_range = 0.0, 0.0 waves = spectrum.wavelengths refls = spectrum.reflectances #perform the ndvi based test nir_start = closest_array_index(self._ndvi_nir_range[0], waves) nir_end = closest_array_index(self._ndvi_nir_range[1], waves) red_start = closest_array_index(self._ndvi_red_range[0], waves) red_end = closest_array_index(self._ndvi_red_range[1], waves) nir_mean = np.mean(refls[nir_start:nir_end]) red_mean = np.mean(refls[red_start:red_end]) self._ndvi = (nir_mean - red_mean) / (nir_mean + red_mean) if self._ndvi < self._ndvi_thresh: return (False, self._ndvi, self._reflectance_range) #perform reflectance range based test #consider the middle 90% of wavelengths chop_size = np.size(refls) * 5 / 100 + 1 start = chop_size stop = np.size(refls) - chop_size self._reflectance_range = np.ptp(refls[start:stop]) if self._reflectance_range < self._reflectance_range_thresh: return (False, self._ndvi, self._reflectance_range) #it is green vegetation if this point is reached return (True, self._ndvi, self._reflectance_range)
def detect(self, spectrums): #check the input is in the right format if not isinstance(spectrums, list) or (len(spectrums) < 3): print("spectrums must be a list of Spectrum objects") sys.exit(0) #check wavelengths are same for all spectrums w0 = spectrums[0].wavelengths if not np.all([np.allclose(w0, s.wavelengths) for s in spectrums]): print("spectrums must have same wavelengths") sys.exit(0) #assemble the reflectances in a matrix #one row = one spectrum's reflectances refls = np.empty((len(spectrums), np.size(w0)), dtype = np.double) for (r, s) in enumerate(spectrums): refls[r, :] = np.copy(s.reflectances.transpose()) #find the median spectrum median = np.median(refls, axis = 0) #compute median of absolute deviations from median mad = np.median(np.abs(refls - median), axis = 0) #compute robust estimate of standard deviation sigma = mad/0.67 #compute the zscores zs = (refls - median)/sigma #range indices to look for abnormal deviations rngidxs = [] for rng in self._ranges: start = closest_array_index(rng[0], w0) end = closest_array_index(rng[1], w0) + 1 rngidxs.append(start, end) #do the outlier detection inliers = [] outliers = [] for (specidx, spec) in enumerate(spectrums): outlier = False for (start, end) in rngidxs: if np.any(np.abs(zs[specidx, start:end]) > self._zthresh): outlier = True if outlier: outliers.append(spec) else: inliers.append(spec) #store some stuff in class - useful for plotting self._median = median self._std = sigma return (inliers, outliers)
def _correct_postzones(self): zones = range(self._stablezone + 1, len(self._jumpwaves) + 1) for z in zones: ix = closest_array_index(self._jumpwaves[z - 1], self._dm[:, 0]) sjump = self._dm[ix, 1] - self._dm[(ix - 1), 1] ujump = self._dm[(ix + 2), 1] - self._dm[(ix + 1), 1] avjump = (sjump + ujump) / 2.0 scale = (self._dm[ix, 1] + avjump) / self._dm[(ix + 1), 1] self._dm[(ix + 1):, 1] = self._dm[(ix + 1):, 1] * scale
def _correct_prezones(self): zones = range(self._stablezone - 1, -1, -1) for z in zones: ix = closest_array_index(self._jumpwaves[z], self._dm[:, 0]) sjump = self._dm[ix, 1] - self._dm[(ix + 1), 1] ujump = self._dm[(ix - 2), 1] - self._dm[(ix - 1), 1] avjump = (sjump + ujump) / 2.0 scale = (self._dm[ix, 1] + avjump) / self._dm[(ix - 1), 1] self._dm[0:ix, 1] = self._dm[0:ix, 1] * scale
def _correct_postzones(self): zones = range(self._stablezone + 1, len(self._jumpwaves) + 1) for z in zones: ix = closest_array_index(self._jumpwaves[z - 1], self._dm[:, 0]) sjump = self._dm[ix, 1] - self._dm[(ix - 1), 1] ujump = self._dm[(ix + 2), 1] - self._dm[(ix + 1), 1] avjump = (sjump + ujump)/2.0 scale = (self._dm[ix, 1] + avjump)/self._dm[(ix + 1), 1] self._dm[(ix + 1):, 1] = self._dm[(ix + 1):, 1]*scale
def _correct_prezones(self): zones = range(self._stablezone - 1, -1, -1) for z in zones: ix = closest_array_index(self._jumpwaves[z], self._dm[:, 0]) sjump = self._dm[ix, 1] - self._dm[(ix + 1), 1] ujump = self._dm[(ix - 2), 1] - self._dm[(ix - 1), 1] avjump = (sjump + ujump)/2.0 scale = (self._dm[ix, 1] + avjump)/self._dm[(ix - 1), 1] self._dm[0:ix, 1] = self._dm[0:ix, 1]*scale
def process_overlap(self, spec): #find the forward difference for the wavelengths diffs = np.diff(spec.wavelengths) #find where the wavelength differences are negative idxs = np.nonzero(diffs <= -0.05)[0] idxs = idxs + 1 idxs = np.hstack((np.array([0]), idxs, np.size(spec.wavelengths))) #create pieces os spectrums with increasing wavelengths pcs = [] data = spec.data uniquifier = WaveUniquifier() for k in range(1, len(idxs)): i1 = idxs[k - 1] i2 = idxs[k] s = Spectrum(data = data[i1:i2, :], idstr = spec.idstr, company = spec.company, instrument = spec.instrument) pcs.append(uniquifier.uniquify(s)) #resample the pieces into 1 nm wavelengths rspcs = [] resampler = WaveResampler() for s in pcs: wr = s.wavelength_range() start = math.ceil(wr[0]) stop = math.floor(wr[1]) resampler = WaveResampler(rstype = self._rstype, wavestart = start, wavestop = stop, spacing = 1.0) rspcs.append(resampler.resample(s)) # print(rspcs[-1].wavelengths[0], rspcs[-1].wavelengths[-1]) # print("------------------------") #chop and stitch if len(rspcs) > 1: #find the wavelengths to chop at critwaves = [rspcs[0].wavelengths[0]] for i in range(1, len(rspcs)): #find the overlapping indices lstart, lstop, rstart, rstop = -1, -1, -1, -1 rstart = 0 lstart = closest_array_index(rspcs[i].wavelengths[0], rspcs[i - 1].wavelengths) lstop = len(rspcs[i - 1].wavelengths) rstop = closest_array_index(rspcs[i - 1].wavelengths[-1], rspcs[i].wavelengths) + 1 lrefls = rspcs[i - 1].reflectances[lstart:lstop] rrefls = rspcs[i].reflectances[rstart:rstop] lwaves = rspcs[i - 1].wavelengths[lstart:lstop] critwaves.append(lwaves[np.argmin(np.abs(lrefls - rrefls))]) critwaves.append(rspcs[-1].wavelengths[-1]) # print("critwaves = {}".format(critwaves)) subdms = [] for i in range(len(rspcs)): start = closest_array_index(critwaves[i], rspcs[i].wavelengths) stop = closest_array_index(critwaves[i + 1], rspcs[i].wavelengths) + 1 subdms.append(rspcs[i].data[start:stop, :]) # print(rspcs[i].data[start:stop, :]) # print("========================") return uniquifier.uniquify(Spectrum(data = np.vstack(tuple(subdms)), idstr = spec.idstr, company = spec.company, instrument = spec.instrument)) else: return rspcs[0]