Lets open up ms paint and draw a cluster .

That is an upscale picture of a 60×60 manually drawn bmp file
This file will probably be fed into our code and the code should rework it in order that the
course with the largest variance sits on the x axis (if i understood issues proper).
So , some preliminary stuff , open the file , useful resource it , learn the pixels , flip them to samples.
Our samples will seem like this , now we have one class , no fancy stuff.
class a_sample{ public: int x,y,cluster; double xd,yd; a_sample(void){x=0;y=0;cluster=0;} };
Ignore the cluster studying it was meant for an additional check -which failed-
These are the inputs we’ll be working with :
#embrace <CanvasCanvas.mqh>; enter string testBMP="test_2.bmp"; enter shade fillColor=C'255,0,0'; enter shade BaseColor=clrWheat; enter bool RemoveCovariance=false;
We learn the picture and switch every pixel that’s pink (or that matches our shade enter) to a pattern.
if(ResourceCreate("TESTRESOURCE","Recordsdata"+testBMP)){ uint pixels[],width,top; if(ResourceReadImage("::TESTRESOURCE",pixels,width,top)){ int total_samples=0; uint seize=ColorToARGB(fillColor,255); ArrayResize(samples,width*top,0); originalX=(int)width; originalY=(int)top; int co=-1; for(int y=0;y<(int)top;y++){ for(int x=0;x<(int)width;x++){ co++; if(pixels[co]==seize){ total_samples++; samples[total_samples-1].x=x; samples[total_samples-1].y=y; samples[total_samples-1].xd=x; samples[total_samples-1].yd=y; } } } ArrayResize(samples,total_samples,0); Print("Discovered "+IntegerToString(total_samples)+" samples"); } }
Neat , now we cross the samples right into a matrix that’s scaled with every pattern being a row and every function (x,y) being a column
matrix unique; unique.Init(total_samples,2); for(int i=0;i<total_samples;i++){ unique[i][0]=samples[i].xd; unique[i][1]=samples[i].yd; }
So we form (resize) the matrix to have whole samples # of rows and a pair of columns (x , y) . X+Y are our pattern options on this instance.
We then assemble , effectively not we however the mq library costructs the covariance matrix , we cross false within the parameter as our options sit on the columns . The place our options on the rows , i.e. one row was one function then we might name this perform utilizing true.
matrix covariance_matrix=unique.Cov(false);
What’s the covariance matrix ? it’s a options by options (options x options) (2×2) matrix that measures the covariance of every function to all different options . Neat that we will use one line of code .
Then we’d like the eigenvectors and eigenvalues of that 2×2 covariance matrix
The speculation i do not fairly understands states that it will point out the “course” of most “variance”.
Let’s play alongside
matrix eigenvectors; vector eigenvalues; if(covariance_matrix.Eig(eigenvectors,eigenvalues)){ Print("Eigenvectors"); Print(eigenvectors); Print("Eigenvalues"); Print(eigenvalues); }else{Print("Cannot Eigen");}
the eigenvectors will probably be a 2×2 matrix as effectively if i am not mistaken , identical because the covariance martix.
Now , let’s take our samples and “flip” them in order that probably the most various course sits on the x axis.If that is the way it works and it was not random.
Visualize what we expect to see right here based mostly on the primary picture posted.
That is how , thus far :
for(int i=0;i<total_samples;i++){ vector thissample={samples[i].xd,samples[i].yd}; thissample=thissample.MatMul(eigenvectors); samples[i].xd=thissample[0]; samples[i].yd=thissample[1]; }
I am developing a vector that’s one pattern , so 2 parts then matrix multiply it with the eigenvectors matrix then cross the ensuing x and y again to the samples .
Then some transformation once more , the reason being there may be to accommodate a number of eigenvector passes , you most likely will get the identical concept.
double minX=INT_MAX,maxX=INT_MIN,minY=INT_MAX,maxY=INT_MIN; for(int i=0;i<total_samples;i++){ if(samples[i].xd>maxX){maxX=samples[i].xd;} if(samples[i].xd<minX){minX=samples[i].xd;} if(samples[i].yd>maxY){maxY=samples[i].yd;} if(samples[i].yd<minY){minY=samples[i].yd;} } double rangeX=maxX-minX; double rangeY=maxY-minY; double allMax=MathMax(maxX,maxY); double allMin=MathMin(minX,minY); double allRange=allMax-allMin; for(int i=0;i<total_samples;i++){ samples[i].xd=((samples[i].xd-minX)/rangeX)*1000.0; samples[i].yd=((samples[i].yd-minY)/rangeY)*1000.0; samples[i].x=(int)samples[i].xd; samples[i].y=(int)samples[i].yd; } originalX=1000; originalY=1000;
Then the drawing half which isn’t that necessary .
that is the result

The samples touching the sides is extra as a consequence of our reconstruction however the transformation occured.
Right here is the complete code , i’ve left my errors in commented out , and likewise the removeCovariance isn’t working.
In case you discover points let me know.
Now think about you’ve 1000 options proper ? you can not plot all that so how will we assemble a brand new function that may be a artificial weighted sum of the outdated options based mostly on the eigenvectors (if i am heading in the right direction right here) . Like Precept part evaluation .
#property model "1.00" #embrace <CanvasCanvas.mqh>; enter string testBMP="test_2.bmp"; enter shade fillColor=C'255,0,0'; enter shade BaseColor=clrWheat; enter bool RemoveCovariance=false; string system_tag="TEST_"; class a_sample{ public: int x,y,cluster; double xd,yd; a_sample(void){x=0;y=0;cluster=0;} }; int DISPLAY_X,DISPLAY_Y,originalX,originalY; double PIXEL_RATIO_X=1.0,PIXEL_RATIO_Y=1.0; bool READY=false; a_sample samples[]; CCanvas DISPLAY; int OnInit() { ArrayFree(samples); DISPLAY_X=0; DISPLAY_Y=0; originalX=0; originalY=0; PIXEL_RATIO_X=1.0; PIXEL_RATIO_Y=1.0; READY=false; ObjectsDeleteAll(ChartID(),system_tag); EventSetMillisecondTimer(44); ResourceFree("TESTRESOURCE"); return(INIT_SUCCEEDED); } void OnTimer(){ EventKillTimer(); if(ResourceCreate("TESTRESOURCE","Recordsdata"+testBMP)){ uint pixels[],width,top; if(ResourceReadImage("::TESTRESOURCE",pixels,width,top)){ int total_samples=0; uint seize=ColorToARGB(fillColor,255); ArrayResize(samples,width*top,0); originalX=(int)width; originalY=(int)top; int co=-1; for(int y=0;y<(int)top;y++){ for(int x=0;x<(int)width;x++){ co++; if(pixels[co]==seize){ total_samples++; samples[total_samples-1].x=x; samples[total_samples-1].y=y; samples[total_samples-1].xd=x; samples[total_samples-1].yd=y; } } } ArrayResize(samples,total_samples,0); Print("Discovered "+IntegerToString(total_samples)+" samples"); matrix unique; unique.Init(total_samples,2); for(int i=0;i<total_samples;i++){ unique[i][0]=samples[i].xd; unique[i][1]=samples[i].yd; } matrix covariance_matrix=unique.Cov(false); Print("Covariance matrix"); Print(covariance_matrix); matrix eigenvectors; vector eigenvalues; matrix inverse_covariance_matrix=covariance_matrix.Inv(); if(covariance_matrix.Eig(eigenvectors,eigenvalues)){ Print("Eigenvectors"); Print(eigenvectors); Print("Eigenvalues"); Print(eigenvalues); for(int i=0;i<total_samples;i++){ vector thissample={samples[i].xd,samples[i].yd}; thissample=thissample.MatMul(eigenvectors); samples[i].xd=thissample[0]; samples[i].yd=thissample[1]; if(RemoveCovariance){ samples[i].xd/=MathSqrt(eigenvalues[0]); samples[i].yd/=MathSqrt(eigenvalues[1]); } } double minX=INT_MAX,maxX=INT_MIN,minY=INT_MAX,maxY=INT_MIN; for(int i=0;i<total_samples;i++){ if(samples[i].xd>maxX){maxX=samples[i].xd;} if(samples[i].xd<minX){minX=samples[i].xd;} if(samples[i].yd>maxY){maxY=samples[i].yd;} if(samples[i].yd<minY){minY=samples[i].yd;} } double rangeX=maxX-minX; double rangeY=maxY-minY; double allMax=MathMax(maxX,maxY); double allMin=MathMin(minX,minY); double allRange=allMax-allMin; for(int i=0;i<total_samples;i++){ samples[i].xd=((samples[i].xd-minX)/rangeX)*1000.0; samples[i].yd=((samples[i].yd-minY)/rangeY)*1000.0; samples[i].x=(int)samples[i].xd; samples[i].y=(int)samples[i].yd; } originalX=1000; originalY=1000; }else{Print("Can not eigen");} build_deck(originalX,originalY); READY=true; }else{ Print("Can not learn picture"); } }else{ Print("Can not load file"); } ExpertRemove(); Print("DONE"); } void build_deck(int img_x, int img_y){ int screen_x=(int)ChartGetInteger(ChartID(),CHART_WIDTH_IN_PIXELS,0); int screen_y=(int)ChartGetInteger(ChartID(),CHART_HEIGHT_IN_PIXELS,0); int btn_height=40; screen_y-=btn_height; double img_x_by_y=((double)img_x)/((double)img_y); int test_x=screen_x; int test_y=(int)(((double)test_x)/img_x_by_y); if(test_y>screen_y){ test_y=screen_y; test_x=(int)(((double)test_y)*img_x_by_y); } int px=(screen_x-test_x)/2; int py=(screen_y-test_y)/2; DISPLAY.CreateBitmapLabel(ChartID(),0,system_tag+"_display",px,py,test_x,test_y,COLOR_FORMAT_ARGB_NORMALIZE); DISPLAY_X=test_x; DISPLAY_Y=test_y; DISPLAY.Erase(0); PIXEL_RATIO_X=((double)(DISPLAY_X))/((double)(img_x)); PIXEL_RATIO_Y=((double)(DISPLAY_Y))/((double)(img_y)); PIXEL_RATIO_X=MathMax(1.0,PIXEL_RATIO_X); PIXEL_RATIO_Y=MathMax(1.0,PIXEL_RATIO_Y); PIXEL_RATIO_X=8.0; PIXEL_RATIO_Y=8.0; update_deck(); } void update_deck(){ DISPLAY.Erase(ColorToARGB(clrBlack,255)); uint BASECOLOR=ColorToARGB(BaseColor,255); for(int i=0;i<ArraySize(samples);i++){ double newx=(((double)samples[i].x)/((double)originalX))*((double)DISPLAY_X); double newy=(((double)samples[i].y)/((double)originalY))*((double)DISPLAY_Y); int x1=(int)MathFloor(newx-PIXEL_RATIO_X/2.00); int x2=(int)MathFloor(newx+PIXEL_RATIO_X/2.00); int y1=(int)MathFloor(newy-PIXEL_RATIO_Y/2.00); int y2=(int)MathFloor(newy+PIXEL_RATIO_Y/2.00); DISPLAY.FillRectangle(x1,y1,x2,y2,BASECOLOR); } DISPLAY.Replace(true); ChartRedraw(); } void OnDeinit(const int purpose) { } void OnTick() { }