Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JPgraph] Probleem genereren spline grafiek

Pagina: 1
Acties:

  • Crayne
  • Registratie: Januari 2002
  • Laatst online: 17-03 13:41

Crayne

Have face, will travel

Topicstarter
Ik ben voor mijn vrouw een kleine tool in elkaar aan het draaien die haar in staat stelt om haar cyclus bij te houden en eventueel te temperaturen. Deze temperaturen zouden dan vervolgens tot een grafiekje verwerkt moeten worden. Dit werkt prima wanneer het aantal meetpunten heel laag is (bij 6 is er geen enkel probleem), maar wanneer ik een grotere range wil zien, zeg 10, dan krijg ik een foutmelding die niet van toepassing zou moeten zijn.
Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.
Om specifiek te zijn: hij zegt dat element [0] en element [0] gelijk zijn en hij dus de grafiek niet kan genereren. Heel typisch, dat die twee gelijk zijn. *kuch*

Wat doe ik?

Allereerst heb ik dus in de database een aantal data zitten met daarbij een temperatuur. Deze worden uit de db gehaald en vervolgens in de volgende code aan Jpgraph aangeboden:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
try
{
        
    $aResult = $oDB->query($sQuery, 'recordset');
            
}
catch (CustomException $oException)
{
                    
    $oException->showError(9);
                    
}

$aX = $aY = array();
        
foreach ($aResult as $aRecord)
{
    
    $aX[] = strtotime($aRecord['date']);
    $aY[] = (float) $aRecord['temp'];
            
}

$oSpline = new Spline($aX, $aY);

list($aNewX, $aNewY) = $oSpline->Get((count($aX) * 50));
            
$oGraph = new Graph((55 * count($aX)), 300);
            
$oGraph->SetMargin(40, 20, 40, 30);
$oGraph->title->Set('Temperatuurgrafiek test');
$oGraph->title->SetFont(FF_ARIAL, FS_NORMAL, 12);
$oGraph->SetMarginColor('lightblue');
$oGraph->SetScale('datlin');
$oGraph->xgrid->Show();
$oGraph->xaxis->SetLabelFormatString('d-m', true);
$oGraph->yaxis->SetLabelFormat('%1.1f');
$oGraph->img->SetImgFormat('png');

$oScatterplot = new ScatterPlot($aY, $aX);
$oScatterplot->mark->SetFillColor('red@0.3');
$oScatterplot->mark->SetColor('red@0.5');
            
$oLineplot = new LinePlot($aNewY, $aNewX);
$oLineplot->SetColor('navy');

$oGraph->Add($oLineplot);
$oGraph->Add($oScatterplot);

$sFilename = "./graphs/grafiek_".date('Ymd', time()).".png";
            
if (file_exists($sFilename))
{
            
    unlink($sFilename);
                
}
            
$oGraph->Stroke($sFilename);


De fout treedt op in de aanroep van de Get method van het Spline object. Deze dient voor zover ik kan zien om een voldoende hoog aantal punten te leveren zodat er vloeiende lijnen kunnen worden getrokken. Binnen deze method wordt de method Interpolate aangeroepen en in deze method wordt de fout gegenereerd (zo leert debuggen mij.) Ik heb alleen geen enkel idee wat deze method precies voor elkaar probeert te krijgen of waarom hij een foutmelding genereert die niet klopt.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    // Return a single interpolated Y-value from an x value
    function Interpolate($xpoint) {

        $max = $this->n-1;
        $min = 0;

        // Binary search to find interval
        while( $max-$min > 1 ) {
            $k = ($max+$min) / 2;
            if( $this->xdata[$k] > $xpoint )
            $max=$k;
            else
            $min=$k;
        }

        // Each interval is interpolated by a 3:degree polynom function
        $h = $this->xdata[$max]-$this->xdata[$min];

        if( $h == 0  ) {
            JpGraphError::RaiseL(19002);
            //('Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.');
        }


        $a = ($this->xdata[$max]-$xpoint)/$h;
        $b = ($xpoint-$this->xdata[$min])/$h;
        return $a*$this->ydata[$min]+$b*$this->ydata[$max]+
        (($a*$a*$a-$a)*$this->y2[$min]+($b*$b*$b-$b)*$this->y2[$max])*($h*$h)/6.0;
    }


Als ik debug en $min en $max laat zien krijg ik het volgende:

PHP:
1
2
3
int(0)

float(0.5625)


Element $aX[0.5625] wordt door PHP dus herleid naar element 0 (niet raar) en vervolgens concludeert hij dat er één of meer elementen gelijk aan elkaar zijn. Ik heb ook geprobeerd de foutmelding gewoon keihard uit te commenten, maar de grafiek die dan gegenereert wordt klopt vervolgens ook niet:

Afbeeldingslocatie: http://i59.photobucket.com/albums/g300/CrayneNL/got/grafiek_20110909.png

De input voor de x-as is de volgende array:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
array(10) {
  [0]=>
  int(1314835200)
  [1]=>
  int(1315008000)
  [2]=>
  int(1315094400)
  [3]=>
  int(1315353600)
  [4]=>
  int(1315526400)
  [5]=>
  int(1315612800)
  [6]=>
  int(1313798400)
  [7]=>
  int(1314057600)
  [8]=>
  int(1314316800)
  [9]=>
  int(1314403200)
}


Input voor de y-as is de volgende array:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
array(10) {
  [0]=>
  float(37.1)
  [1]=>
  float(36.9)
  [2]=>
  float(36.8)
  [3]=>
  float(37.2)
  [4]=>
  float(38.2)
  [5]=>
  float(37.5)
  [6]=>
  float(37.2)
  [7]=>
  float(37.4)
  [8]=>
  float(37.3)
  [9]=>
  float(37.2)
}


Zoals je ziet zijn alle waarden in de array met data voor de x-as uniek. Het is mij dus een raadsel waarom deze foutmelding optreedt of hoe ik hem zou moeten voorkomen. Is er iemand die me kan vertellen wat de functie Interpolate precies doet en waarom mijn input arrays deze foutmelding veroorzaken?

Mijn Library Thing catalogus


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13:05

Janoz

Moderator Devschuur®

!litemod

Het lijkt me dat het mis gaat omdat de waarden voor de X-as niet oplopend zijn. Vanaf het 6e punt van je grafiek gaat de waarde van X weer een stuk naar beneden. Als je de lijn dus tekent (die begint bij punt 0 en dan via 1,2,3,4,5 naar 6 gaat) gaat deze lijn weer terug naar voor het begonnen is. Dan zijn er dus bij een gegeven X waarde meerdere waarden voor Y.

[ Voor 30% gewijzigd door Janoz op 09-09-2011 14:15 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Crayne
  • Registratie: Januari 2002
  • Laatst online: 17-03 13:41

Crayne

Have face, will travel

Topicstarter
AARGH! *zucht*

Een simpele ORDER BY lost het probleem helemaal op. Omdat de timestamps niet in oplopende volgorde worden aangeboden, klapt de JpGraph module er uit.

Ik laat even in het midden of dat een net iets is. ;)

[ Voor 14% gewijzigd door Crayne op 09-09-2011 14:26 ]

Mijn Library Thing catalogus