I've been tasked with implementing a Normal Distribution graph. I was wondering if Chart.js offers this functionality right out of the box or if I will need to extend it. The graph in question is here
Thank you
It is unfortunately not possible with Chart.js, except if you create it by yourself.
But, I found a library called ChartNew.js (Github) that provides a lot of functionalities that are not available on Chart.js :
Chart.js has been completely rewritten since ChartNew.js has been developed; Both code are now completely different. Most of the functionalities inserted in the new version of Chart.js are also available in ChartNew.js
And this library provides a Gaussian Function (also called Normal Distribution) :
To do it, take a look at the sample given in the Github.
I'm sure it will suit you if you change some data.
This Implementation has been done using React. The functions below can still be used in other programming languages built on top of Javascript.
The only two inputs required to plot a Normal Distribution curve will be Mean and Standard deviation
Defining states for mean and standard deviation & states for X and Y arrays
const [bellMean, setBellMean] = useState<number>(12.2036); //example
const [bellStdev, setBellStdev] = useState<number>(0.0008); //example
const [bellXValues, setBellXValues] = useState<(number)[]>([]);
const [bellYValues, setBellYValues] = useState<(number | null)[]>([]);
To Get X values for bell curve (if not using react can get rid of useEffect)
useEffect(() => {
// defining chart limits between which the graph will be plotted
let lcl = bellMean - bellStdev * 6;
let ucl = bellMean + bellStdev * 6;
let ticks = [lcl];
let steps = 100; // steps corresponds to the size of the output array
let stepSize = Math.round(((ucl - lcl) / steps) * 10000) / 10000;
let tickVal = lcl;
for (let i = 0; i <= steps; i++) {
ticks.push(Math.round(tickVal * 10000) / 10000); // rounding off to 4 decimal places
tickVal = tickVal + stepSize;
}
setBellXValues(ticks); //array for X values
}, [bellMean, bellStdev]);
To Get Y values for Bell curve (if not using react can get rid of useEffect)
useEffect(() => {
// Using PDF function from vega-statistics instead of importing the whole library
const densityNormal = (value: number, mean: number, stdev: number) => {
const SQRT2PI = Math.sqrt(2 * Math.PI);
stdev = (stdev == null) ? 1 : stdev;
const z = (value - (mean || 0)) / stdev;
return Math.exp(-0.5 * z * z) / (stdev * SQRT2PI);
};
let YValues = bellXValues.map((item: number) => {
if (bellMean === null || bellStdev === undefined) {
return null;
} else {
const pdfValue = densityNormal(item, bellMean, bellStdev);
return pdfValue === Infinity ? null : pdfValue;
}
});
setBellYValues(YValues); // array for Y values
}, [bellXValues]);
The arrays for X and Y can be fed to labels and data props of chartjs as it is.
Related
I want to write an audio code in c++ for my microcontroller-based synthesizer which should allow me to generate a sampled square wave signal using the Fourier Series equation.
My question in general is: is there a way to set an "unknown" variable like "x" inside a sine-equation, and change its value afterwards?
What do I mean by that:
If you take a look on my code i've written so far you see the following:
void SquareWave(int mHarmonics){
char x;
for(int k = 0; k <= mHarmonics; k++){
mFourier += 1/((2*k)+1)*sin(((2*k)+1)*2*M_PI*x/SAMPLES_TOTAL);
}
for(x = (int)0; x < SAMPLES_TOTAL; x++){
mWave[x] = mFourier;
}
}
Inside the first for loop mFourier is summing weighted sinus-signals dependent by the number of Harmonics "mHarmonics". So a note on my keyboard should be setting up the harmonic spectrum automatically.
In this equation I've set x as a character and now we get to the center of my problem because i want to set x as a "unknown" variable which has a value that i want to set afterwards and if x would be an integer it would have some standard value like 0, which would make the whole equation incorrect.
In the bottom loop i want to write this Fourier Series sum inside an array mWave, which will be the resulting output. Is there a possibility to give the sum to mWave[x], where x is a "unknown" multiplier inside the sine signal first, and then change its values afterwards inside the second loop?
Sorry if this is a stupid question, I have not much experience with c++ but I try to learn it by making these stupid mistakes!
Cheers
#Useless told you what to do, but I am going to try to spell it out for you.
This is how I would do it:
#include <vector>
/**
* Perform a rectangular window in the frequency domain of a time domain square
* wave. This should be a sync impulse response.
*
* #param x The time domain sample within the period of the signal.
* #param harmonic_count The number of harmonics to aggregate in the result.
* #param sample_count The number of samples across the square wave period.
*
* #return double The time domain result of the combined harmonics at point x.
*/
double box_car(unsigned int x,
unsigned int harmonic_count,
unsigned int sample_count)
{
double mFourier = 0.0;
for (int k = 0; k <= harmonic_count; k++)
{
mFourier += 1.0 / ((2 * k) + 1) * sin(((2 * k) + 1) * 2.0 * M_PI * x / sample_count);
}
return mFourier;
}
/**
* Calculate the suqare wave samples across the time domain where the samples
* are filtered to only include the harmonic_count.
*
* #param harmonic_count The number of harmonics to aggregate in the result.
* #param sample_count The number of samples across the square wave period.
*
* #return std::vector<double>
*/
std::vector<double> box_car_samples(unsigned int harmonic_count,
unsigned int sample_count)
{
std::vector<double> square_wave;
for (unsigned int x = 0; x < sample_count; x++)
{
double sample = box_car(x, harmonic_count, sample_count);
square_wave.push_back(sample);
}
return square_wave;
}
So mWave[x] is returned as a std::vector of doubles (floating point).
The function box_car_samples() is f(k, x) as stated before.
So since I can't use vectors inside Arduino IDE anyhow I've tried the following solution:
...
void ComputeBandlimitedSquareWave(int mHarmonics){
for(int i = 0; i < sample_count; i++){
mWavetable[i] = ComputeFourierSeriesSquare(x);
if (x < sample_count) x++;
}
}
float ComputeFourierSeriesSquare(int x){
for(int k = 0; k <= mHarmonics; k++){
mFourier += 1/((2*k)+1)*sin(((2*k)+1)*2*M_PI*x/sample_count);
return mFourier;
}
}
...
First I thought this must be right a minute ago, but my monitors prove me wrong...
It sounds like a completely messed up sum of signals first, but after about 2 seconds the true characterisic squarewave sound comes through. I try to figure out what I'm overseeing and keep You guys updated if I can isolate that last part coming through my speakers, because it actually has a really decent sound. Only the messy overlays in the beginning are making me desperate right now...
I am developing the nearest Food Dish application location. I managed to display it based on the location closest to the user, using this plugin great_circle_distance
I want to know how to set the max radius? ex. < 30 Km
Here my code:
_foodByCategories.sort((a, b) {
var distance1 = new GreatCircleDistance.fromDegrees(
latitude1:
model.userLocation == null ? 0.0 : model.userLocation["latitude"],
longitude1: model.userLocation == null
? 0.0
: model.userLocation["longitude"],
latitude2: a.lat,
longitude2: a.long);
double totaldistance1 = distance1.haversineDistance();
var distance2 = new GreatCircleDistance.fromDegrees(
latitude1:
model.userLocation == null ? 0.0 : model.userLocation["latitude"],
longitude1: model.userLocation == null
? 0.0
: model.userLocation["longitude"],
latitude2: b.lat,
longitude2: b.long);
double totaldistance2 = distance2.haversineDistance();
return (totaldistance1 - totaldistance2).toInt();
});
Any answer will appreciated.
If I understand your question correct
_foodByCategories.where((a) {
var distance = new GreatCircleDistance.fromDegrees(latitude1: double.parse(widget.lat), longitude1: double.parse(widget.lng), latitude2: double.parse(a.lat), longitude2: double.parse(a.lng));
var totaldistance = distance.haversineDistance().toStringAsFixed(2);
double distanceDouble1 = double.parse(totaldistance);
return distance <= 30000; // or something like that
}).sort ... // and your sorting code
I can't see any way to do this within the package you are using. You could suggest to the developer to add this functionality in?
Alternatively, you are getting the total distance in your code so you could just do a simple if statement to check if the total distance is greater than your set max radius.
I’m a beginner in DSP and I have to make an audio equalizer.
I’ve done some research and tried a lot of thing in the past month but in the end, it’s not working and I’m a bit overwhelmed with all those informations (that I certainly don’t interpret well).
I have two main classes : Broadcast (which generate pink noise, and apply gain to it) and Record (which analyse the input of the microphone et deduct the gain from it).
I have some trouble with both, but I’m gonna limit this post to the Broadcast side.
I’m using Aquila DSP Library, so I used this example and extended the logic of it.
/* Constructor */
Broadcast::Broadcast() :
_Info(44100, 2, 2), // 44100 Hz, 2 channels, sample size : 2 octet
_pinkNoise(_Info.GetFrequency()), // Init the Aquila::PinkNoiseGenerator
_thirdOctave() // list of “Octave” class, containing min, center, and max frequency of each [⅓ octave band](http://goo.gl/365ZFN)
{
_pinkNoise.setAmplitude(65536);
}
/* This method is called in a loop and fills the buffer with the pink noise */
bool Broadcast::BuildBuffer(char * Buffer, int BufferSize, int & BufferCopiedSize)
{
if (BufferSize < 131072)
return false;
int SampleCount = 131072 / _Info.GetSampleSize();
int signalSize = SampleCount / _Info.GetChannelCount();
_pinkNoise.generate(signalSize);
auto fft = Aquila::FftFactory::getFft(signalSize);
Aquila::SpectrumType spectrum = fft->fft(_pinkNoise.toArray());
Aquila::SpectrumType ampliSpectrum(signalSize);
std::list<Octave>::iterator it;
double gain, fl, fh;
/* [1.] - The gains are applied in this loop */
for (it = _thirdOctave.begin(); it != _thirdOctave.end(); it++)
{
/* Test values */
if ((*it).getCtr() >= 5000)
gain = 6.0;
else
gain = 0.0;
fl = (signalSize * (*it).getMin() / _Info.GetFrequency());
fh = (signalSize * (*it).getMax() / _Info.GetFrequency());
/* [2.] - THIS is the part that I think is wrong */
for (int i = 0; i < signalSize; i++)
{
if (i >= fl && i < fh)
ampliSpectrum[i] = std::pow(10, gain / 20);
else
ampliSpectrum[i] = 1.0;
}
/* [3.] - Multiply each bin of spectrum with ampliSpectrum */
std::transform(
std::begin(spectrum),
std::end(spectrum),
std::begin(ampliSpectrum),
std::begin(spectrum),
[](Aquila::ComplexType x, Aquila::ComplexType y) { return x * y; }); // Aquila::ComplexType is an std::complex<double>
}
/* Put the IFFT result in a new buffer */
boost::scoped_ptr<double> s(new double[signalSize]);
fft->ifft(spectrum, s.get());
int val;
for (int i = 0; i < signalSize; i++)
{
val = int(s.get()[i]);
/* Fills the two channels with the same value */
reinterpret_cast<int*>(Buffer)[i * 2] = val;
reinterpret_cast<int*>(Buffer)[i * 2 + 1] = val;
}
BufferCopiedSize = SampleCount * _Info.GetSampleSize();
return true;
}
I’m using the pink noise of gStreamer along with the equalizer-nbands module to compare my output.
With all gain set to 0.0 the outputs are the same.
But as soon as I add some gain, the outputs sound different (even though my output still sound like a pink noise, and seems to have gain in the right spot).
So my question is :
How can I apply my gains to each ⅓ Octave band in the frequency domain.
My research shows that I should do a filter bank of band-pass filters, but how to do that with the result of an FFT ?
Thanks for your time.
I am facing the following problem:
I am trying to implement a MNB classifier in a sliding window. I implemented a LinkedList of the size of the window and store all instances of the stream which have to be considered in it. When a new instance arrives which doesn't fit in the window anymore the first instance is removed. To remove the corresponding word counts I implemented the following method which basically is the same as trainOnInstanceImpl() by moa just backwards:
private void removeInstance(Instance instToRemove) {
int classIndex = instToRemove.classIndex();
int classValue = (int) instToRemove.value(classIndex);
double w = instToRemove.weight();
m_probOfClass[classValue] -= w;
m_classTotals[classValue] -= w * totalSize(instToRemove);
double total = m_classTotals[classValue];
for (int i = 0; i < instToRemove.numValues(); i++) {
int index = instToRemove.index(i);
if (index != classIndex && !instToRemove.isMissing(i)) {
double laplaceCorrection = 0.0;
if (m_wordTotalForClass[classValue].getValue(index) == w*instToRemove.valueSparse(i) + this.laplaceCorrectionOption.getValue()) {
laplaceCorrection = this.laplaceCorrectionOption.getValue(); //1.0
}
m_wordTotalForClass[classValue].addToValue(index,
(-1)*(w * instToRemove.valueSparse(i) + laplaceCorrection));
}
}
Now if I output the m_wordTotalForClass[classValue] I get different results for a classical MNB over a stream with 3000 instances from instance 2000-3000 as from the sliding window MNB (see above) with a window Size of 1000. And the only differences are that it outputs a 1 instead of a 0 at some points but not always. I guess this has something to do with the laplace correction. Maybe there is a problem with rounding in the if-statement:
if (m_wordTotalForClass[classValue].getValue(index) == w*instToRemove.valueSparse(i) + this.laplaceCorrectionOption.getValue())
so that we not always enter the part where the laplace value is set.
Does anybody have an idea?
I am kind of going crazy as I have been thinking about where the problem may be for the last three days. Any help would be greatly appreciated!
I followed this tutorial in the mapnik github wiki to make a world map: https://github.com/mapnik/mapnik/wiki/GettingStartedInPython
I modified this example, and have now embedded the code into a Pyside Qt Widget. My question now is, how does one plot points on this map using x and y coordinates, or latitude and longitude points?
Here is the code I'm using to generate the map and to embed it in the widget:
import mapnik
m = mapnik.Map(1200,600)
m.background = mapnik.Color('steelblue')
s = mapnik.Style()
r = mapnik.Rule()
polygon_symbolizer = mapnik.PolygonSymbolizer(mapnik.Color('#f2eff9'))
r.symbols.append(polygon_symbolizer)
line_symbolizer = mapnik.LineSymbolizer(mapnik.Color('rgb(50%,50%,50%)'),0.1)
r.symbols.append(line_symbolizer)
s.rules.append(r)
m.append_style('My Style',s)
ds = mapnik.Shapefile(file='/home/lee/shapefiles/ne_110m_admin_0_countries.shp')
layer = mapnik.Layer('world')
layer.datasource = ds
layer.styles.append('My Style')
m.layers.append(layer)
m.zoom_all()
im = mapnik.Image(1200,600)
mapnik.render(m, im)
qim = QImage()
qim.loadFromData(QByteArray(im.tostring('png')))
label = QLabel(self)
label.setPixmap(QPixmap.fromImage(qim))
self.layout.addWidget(label)
Usually, you would connect your map to a datasource such as a PostGIS or SQLite database and let mapnik populate the points from said database, similar to something like this. Either in a python script or generated from xml.
However, in answer to your question, you could plot Lat/Lon points by creating a new Feature from a WKT string and adding that feature to a mapnik.MemoryDatasource().
Below is a simple snippet from a script using the mapfile found here
First we create our style and add it to our map:
s = mapnik.Style() # style object to hold rules
r = mapnik.Rule() # rule object to hold symbolizers
point_sym = mapnik.PointSymbolizer()
point_sym.filename = './symbols/airport.p.16.png'
r.symbols.append(point_sym) # add the symbolizer to the rule object
s.rules.append(r)
m.append_style('airport point', s)
Now we create our data source and add a Point geometry in WKT format:
ds = mapnik.MemoryDatasource()
f = mapnik.Feature(mapnik.Context(), 1)
f.add_geometries_from_wkt("POINT(-92.289595 34.746481)")
ds.add_feature(f)
Now we must create a new layer, add our style that we created, and add the layer to our map:
player = mapnik.Layer('airport_layer')
#since our map is mercator but you wanted to add lat lon points
#we must make sure our layer projection is set to lat lon
player.srs = longlat.params()
player.datasource = ds
player.styles.append('airport point')
m.layers.append(player)
m.zoom_all()
You can look at the entire script here.
If you need to get a geographic coordinate(ie:lat/lon) from the pixel coordinate, you probably need to add your converter functions.
The Google Maps JS code is as follow could perhaps help :
https://developers.google.com/maps/documentation/javascript/examples/map-coordinates
var TILE_SIZE = 256;
function bound(value, opt_min, opt_max) {
if (opt_min != null) value = Math.max(value, opt_min);
if (opt_max != null) value = Math.min(value, opt_max);
return value;
}
function degreesToRadians(deg) {
return deg * (Math.PI / 180);
}
function radiansToDegrees(rad) {
return rad / (Math.PI / 180);
}
/** #constructor */
function MercatorProjection() {
this.pixelOrigin_ = new google.maps.Point(TILE_SIZE / 2,
TILE_SIZE / 2);
this.pixelsPerLonDegree_ = TILE_SIZE / 360;
this.pixelsPerLonRadian_ = TILE_SIZE / (2 * Math.PI);
}
MercatorProjection.prototype.fromLatLngToPoint = function(latLng,
opt_point) {
var me = this;
var point = opt_point || new google.maps.Point(0, 0);
var origin = me.pixelOrigin_;
point.x = origin.x + latLng.lng() * me.pixelsPerLonDegree_;
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
// about a third of a tile past the edge of the world tile.
var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999,
0.9999);
point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) *
-me.pixelsPerLonRadian_;
return point;
};
MercatorProjection.prototype.fromPointToLatLng = function(point) {
var me = this;
var origin = me.pixelOrigin_;
var lng = (point.x - origin.x) / me.pixelsPerLonDegree_;
var latRadians = (point.y - origin.y) / -me.pixelsPerLonRadian_;
var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) -
Math.PI / 2);
return new google.maps.LatLng(lat, lng);
};