def windowed_smooth(measurements, size=1, population_size=512): """ Returns a new list of measurements with the same length as the source measurements, where each value in the result is calculated as the median and weighted MAD of the nearest +/- size measurements and the measurement itself. For example, if the resulting value for measurement X10 with a size of 2 would be median +/- the weighted MAD of the measurements (X8, X9, X10, X11, X12) Edge conditions are handled so that they are smoothed with partial windows :param measurements: :param size: The extend of the smoothing window. :param population_size: :return: """ window = [] window_populations = [] while len(window) < size + 1: m = measurements[len(window)] window.append(m) window_populations.append( mdists.population(mdists.Distribution([m]), count=population_size)) out = [] for i in range(len(measurements)): pop_combined = [] for p in window_populations: pop_combined += p out.append( ValueUncertainty( mdists.percentile(pop_combined), mdists.weighted_median_average_deviation(pop_combined))) append_index = i + size + 1 if append_index >= len(measurements): window.pop(0) window_populations.pop(0) continue m = measurements[append_index] d = mdists.Distribution([m]) pop = mdists.population(d, population_size) window.append(m) window_populations.append(pop) while len(window) > (2 * size + 1): window.pop(0) window_populations.pop(0) return out
def get_weighted_median(quantities) -> mstats.ValueUncertainty: dist = mstats.create_distribution(quantities) pop = mdist.population(dist) return mstats.ValueUncertainty( mdist.percentile(pop, 0.5), max(0.00001, mdist.weighted_median_average_deviation(pop)) )
def get_median( quantities: typing.List[mstats.ValueUncertainty] ) -> mstats.ValueUncertainty: dist = mstats.create_distribution(quantities) pop = mdist.population(dist) return mstats.ValueUncertainty( mdist.percentile(pop, 0.5), max(0.00001, mdist.weighted_median_average_deviation(pop)) )
def calculate_median(values, uncertainties, color_index=0, plot_name=None): """ :param values: :param uncertainties: :param color_index: :param plot_name: :return: """ try: values = values.values except: pass try: uncertainties = uncertainties.values except: pass measurements = [ (val, unc) for val, unc in zip(values, uncertainties) if not np.isnan(val) and not np.isnan(unc) ] values, uncertainties = zip(*measurements) measurements = mstats.values.join(values, uncertainties) dist = mstats.create_distribution(measurements) pop = mdist.population(dist) median = mstats.ValueUncertainty( mdist.percentile(pop), mdist.weighted_median_average_deviation(pop) ) x = mdist.adaptive_range(dist, 4) y = dist.probabilities_at(x) trace = go.Scatter( x=x, y=y, name=plot_name, fill='tozeroy', mode='lines', line=dict( color=plotting.get_color(color_index) ) ) return dict( measurements=measurements, median=median, trace=trace )
def calculate_median_value(values): if not values or not len(values): return dict(values=[], dist=None, pop=None, median=mstats.ValueUncertainty(0, 0.0001)) dist = mstats.create_distribution(values) pop = mdist.population(dist) median = mstats.ValueUncertainty( mdist.percentile(pop), mdist.weighted_median_average_deviation(pop)) return dict(values=values, dist=dist, pop=pop, median=median)
def add_to_group( segment: Segment, groups: SegmentGroupList, trackway_data: dict ) -> SegmentGroupList: """ :param segment: :param groups: :param trackway_data: :return: """ deviations = [deviation_between(g, segment) for g in groups] if not deviations or min(deviations) > 2: return groups + [SegmentGroup( index=len(groups), segments=[segment], median=segment.median, normalized_median=segment.median / trackway_data['width_median'] )] group_index = deviations.index(min(deviations)) group = groups[group_index] cauldron.step.breathe() dist = mstats.create_distribution([s.median for s in group.segments]) pop = mdist.population(dist) median = mstats.ValueUncertainty( mdist.percentile(pop, 0.5), max(0.00001, mdist.weighted_median_average_deviation(pop)) ) normalized = median / trackway_data['width_median'] replacement_group = SegmentGroup( index=group.index, median=median, segments=group.segments + [segment], normalized_median=normalized ) return ( groups[:group_index] + [replacement_group] + groups[(group_index + 1):] )
def calculate_median(values, uncertainties, color_index=0, plot_name=None): """ :param values: :param uncertainties: :param color_index: :param plot_name: :return: """ try: values = values.values except: pass try: uncertainties = uncertainties.values except: pass measurements = [(val, unc) for val, unc in zip(values, uncertainties) if not np.isnan(val) and not np.isnan(unc)] values, uncertainties = zip(*measurements) measurements = mstats.values.join(values, uncertainties) dist = mstats.create_distribution(measurements) pop = mdist.population(dist) median = mstats.ValueUncertainty( mdist.percentile(pop), mdist.weighted_median_average_deviation(pop)) x = mdist.adaptive_range(dist, 4) y = dist.probabilities_at(x) trace = go.Scatter(x=x, y=y, name=plot_name, fill='tozeroy', mode='lines', line=dict(color=plotting.get_color(color_index))) return dict(measurements=measurements, median=median, trace=trace)
def box_smooth(measurements, size=2, population_size=512): """ :param measurements: :param size: :param population_size: :return: """ out = [] for i in range(0, len(measurements), size): d = mdists.Distribution(measurements[i:(i + size)]) pop = mdists.population(d, count=population_size) median = mdists.percentile(pop) mad = mdists.weighted_median_average_deviation(pop) while len(out) < (i + size): out.append(ValueUncertainty(median, mad)) return out
def calculate_median_value(values): if not values or not len(values): return dict( values=[], dist=None, pop=None, median=mstats.ValueUncertainty(0, 0.0001) ) dist = mstats.create_distribution(values) pop = mdist.population(dist) median = mstats.ValueUncertainty( mdist.percentile(pop), mdist.weighted_median_average_deviation(pop) ) return dict( values=values, dist=dist, pop=pop, median=median )