~ubuntu-branches/ubuntu/saucy/3depict/saucy

« back to all changes in this revision

Viewing changes to src/backend/filters/spectrumPlot.cpp

  • Committer: Package Import Robot
  • Author(s): D Haley
  • Date: 2013-05-17 00:52:39 UTC
  • mfrom: (3.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20130517005239-7bl4mnhkvrhc2ba6
Tags: 0.0.13-1
Upload to unstable 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      spectrumPlot.cpp - Compute histograms of values for valued 3D point data
 
3
 *      Copyright (C) 2013, D Haley 
 
4
 
 
5
 *      This program is free software: you can redistribute it and/or modify
 
6
 *      it under the terms of the GNU General Public License as published by
 
7
 *      the Free Software Foundation, either version 3 of the License, or
 
8
 *      (at your option) any later version.
 
9
 
 
10
 *      This program is distributed in the hope that it will be useful,
 
11
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *      GNU General Public License for more details.
 
14
 
 
15
 *      You should have received a copy of the GNU General Public License
 
16
 *      along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
*/
 
18
#include "spectrumPlot.h"
 
19
 
 
20
#include "../plot.h"
 
21
 
 
22
#include "filterCommon.h"
 
23
 
 
24
//!Error codes
 
25
enum 
 
26
{
 
27
        SPECTRUM_BAD_ALLOC=1,
 
28
        SPECTRUM_BAD_BINCOUNT,
 
29
        SPECTRUM_ABORT_FAIL,
 
30
};
 
31
 
 
32
enum
 
33
{
 
34
        KEY_SPECTRUM_BINWIDTH,
 
35
        KEY_SPECTRUM_AUTOEXTREMA,
 
36
        KEY_SPECTRUM_MIN,
 
37
        KEY_SPECTRUM_MAX,
 
38
        KEY_SPECTRUM_LOGARITHMIC,
 
39
        KEY_SPECTRUM_PLOTTYPE,
 
40
        KEY_SPECTRUM_COLOUR
 
41
};
 
42
 
 
43
//Limit user to one :million: bins
 
44
const unsigned int SPECTRUM_MAX_BINS=1000000;
 
45
 
 
46
const unsigned int SPECTRUM_AUTO_MAX_BINS=25000;
 
47
 
 
48
SpectrumPlotFilter::SpectrumPlotFilter()
 
49
{
 
50
        minPlot=0;
 
51
        maxPlot=150;
 
52
        autoExtrema=true;       
 
53
        binWidth=0.5;
 
54
        plotStyle=0;
 
55
        logarithmic=1;
 
56
 
 
57
        //Default to blue plot
 
58
        r=g=0;
 
59
        b=a=1;
 
60
}
 
61
 
 
62
Filter *SpectrumPlotFilter::cloneUncached() const
 
63
{
 
64
        SpectrumPlotFilter *p = new SpectrumPlotFilter();
 
65
 
 
66
        p->minPlot=minPlot;
 
67
        p->maxPlot=maxPlot;
 
68
        p->binWidth=binWidth;
 
69
        p->autoExtrema=autoExtrema;
 
70
        p->r=r; 
 
71
        p->g=g; 
 
72
        p->b=b; 
 
73
        p->a=a; 
 
74
        p->plotStyle=plotStyle;
 
75
        p->logarithmic = logarithmic;
 
76
 
 
77
 
 
78
        //We are copying wether to cache or not,
 
79
        //not the cache itself
 
80
        p->cache=cache;
 
81
        p->cacheOK=false;
 
82
        p->userString=userString;
 
83
        return p;
 
84
}
 
85
 
 
86
//!Get approx number of bytes for caching output
 
87
size_t SpectrumPlotFilter::numBytesForCache(size_t nObjects) const
 
88
{
 
89
        //Check that we have good plot limits, and bin width. if not, we cannot estimate cache size
 
90
        if(minPlot ==std::numeric_limits<float>::max() ||
 
91
                maxPlot==-std::numeric_limits<float>::max()  || 
 
92
                binWidth < sqrt(std::numeric_limits<float>::epsilon()))
 
93
        {
 
94
                return (size_t)(-1);
 
95
        }
 
96
 
 
97
        return (size_t)((float)(maxPlot- minPlot)/(binWidth))*2*sizeof(float);
 
98
}
 
99
 
 
100
unsigned int SpectrumPlotFilter::refresh(const std::vector<const FilterStreamData *> &dataIn,
 
101
        std::vector<const FilterStreamData *> &getOut, ProgressData &progress, bool (*callback)(bool))
 
102
{
 
103
 
 
104
        if(cacheOK)
 
105
        {
 
106
                //Only report the spectrum plot
 
107
                for(unsigned int ui=0;ui<filterOutputs.size(); ui++)
 
108
                        getOut.push_back(filterOutputs[ui]);
 
109
                return 0;
 
110
        }
 
111
 
 
112
 
 
113
 
 
114
        size_t totalSize=numElements(dataIn,STREAM_TYPE_IONS);
 
115
        
 
116
        unsigned int nBins=2;
 
117
        if(totalSize)
 
118
        {
 
119
 
 
120
                //Determine min and max of input
 
121
                if(autoExtrema)
 
122
                {
 
123
                        progress.maxStep=2;
 
124
                        progress.step=1;
 
125
                        progress.stepName=TRANS("Extrema");
 
126
                
 
127
                        size_t n=0;
 
128
                        minPlot = std::numeric_limits<float>::max();
 
129
                        maxPlot =-std::numeric_limits<float>::max();
 
130
                        //Loop through each type of data
 
131
                        
 
132
                        unsigned int curProg=NUM_CALLBACK;      
 
133
                        for(unsigned int ui=0;ui<dataIn.size() ;ui++)
 
134
                        {
 
135
                                //Only process stream_type_ions. Do not propagate anything,
 
136
                                //except for the spectrum
 
137
                                if(dataIn[ui]->getStreamType() == STREAM_TYPE_IONS)
 
138
                                {
 
139
                                        IonStreamData *ions;
 
140
                                        ions = (IonStreamData *)dataIn[ui];
 
141
                                        for(unsigned int uj=0;uj<ions->data.size(); uj++)
 
142
                                        {
 
143
                                                minPlot = std::min(minPlot,
 
144
                                                        ions->data[uj].getMassToCharge());
 
145
                                                maxPlot = std::max(maxPlot,
 
146
                                                        ions->data[uj].getMassToCharge());
 
147
 
 
148
 
 
149
                                                if(!curProg--)
 
150
                                                {
 
151
                                                        n+=NUM_CALLBACK;
 
152
                                                        progress.filterProgress= (unsigned int)((float)(n)/((float)totalSize)*100.0f);
 
153
                                                        curProg=NUM_CALLBACK;
 
154
                                                        if(!(*callback)(false))
 
155
                                                                return SPECTRUM_ABORT_FAIL;
 
156
                                                }
 
157
                                        }
 
158
                
 
159
                                }
 
160
                                
 
161
                        }
 
162
                
 
163
                        //Check that the plot values have been set (ie not same as initial values)
 
164
                        if(minPlot !=std::numeric_limits<float>::max() &&
 
165
                                maxPlot!=-std::numeric_limits<float>::max() )
 
166
                        {
 
167
                                //push them out a bit to make the edges visible
 
168
                                maxPlot=maxPlot+1;
 
169
                                minPlot=minPlot-1;
 
170
                        }
 
171
 
 
172
                        //Time to move to phase 2       
 
173
                        progress.step=2;
 
174
                        progress.stepName=TRANS("count");
 
175
                }
 
176
 
 
177
 
 
178
 
 
179
                double delta = ((double)maxPlot - (double)(minPlot))/(double)binWidth;
 
180
 
 
181
 
 
182
                //Check that we have good plot limits.
 
183
                if(minPlot ==std::numeric_limits<float>::max() || 
 
184
                        minPlot ==-std::numeric_limits<float>::max() || 
 
185
                        fabs(delta) >  std::numeric_limits<float>::max() || // Check for out-of-range
 
186
                         binWidth < sqrt(std::numeric_limits<float>::epsilon()) )
 
187
                {
 
188
                        //If not, then simply set it to "1".
 
189
                        minPlot=0; maxPlot=1.0; binWidth=0.1;
 
190
                }
 
191
 
 
192
 
 
193
 
 
194
                //Estimate number of bins in floating point, and check for potential overflow .
 
195
                float tmpNBins = (float)((maxPlot-minPlot)/binWidth);
 
196
 
 
197
                //If using autoextrema, use a lower limit for max bins,
 
198
                //as we may just hit a nasty data point
 
199
                if(autoExtrema)
 
200
                        tmpNBins = std::min(SPECTRUM_AUTO_MAX_BINS,(unsigned int)tmpNBins);
 
201
                else
 
202
                        tmpNBins = std::min(SPECTRUM_MAX_BINS,(unsigned int)tmpNBins);
 
203
                
 
204
                nBins = (unsigned int)tmpNBins;
 
205
 
 
206
                if (!nBins)
 
207
                {
 
208
                        nBins = 10;
 
209
                        binWidth = (maxPlot-minPlot)/nBins;
 
210
                }
 
211
        }
 
212
 
 
213
 
 
214
        PlotStreamData *d;
 
215
        d=new PlotStreamData;
 
216
        try
 
217
        {
 
218
                d->xyData.resize(nBins);
 
219
        }
 
220
        catch(std::bad_alloc)
 
221
        {
 
222
 
 
223
                delete d;
 
224
                return SPECTRUM_BAD_ALLOC;
 
225
        }
 
226
 
 
227
        
 
228
        d->r = r;
 
229
        d->g = g;
 
230
        d->b = b;
 
231
        d->a = a;
 
232
 
 
233
        d->logarithmic=logarithmic;
 
234
        d->plotStyle = plotStyle;
 
235
        d->plotMode=PLOT_MODE_1D;
 
236
 
 
237
        d->index=0;
 
238
        d->parent=this;
 
239
        d->dataLabel = getUserString();
 
240
        d->yLabel= TRANS("Count");
 
241
 
 
242
        //Check all the incoming ion data's type name
 
243
        //and if it is all the same, use it for the plot X-axis
 
244
        std::string valueName;
 
245
        for(unsigned int ui=0;ui<dataIn.size() ;ui++)
 
246
        {
 
247
                switch(dataIn[ui]->getStreamType())
 
248
                {
 
249
                        case STREAM_TYPE_IONS: 
 
250
                        {
 
251
                                const IonStreamData *ionD;
 
252
                                ionD=(const IonStreamData *)dataIn[ui];
 
253
                                if(!valueName.size())
 
254
                                        valueName=ionD->valueType;
 
255
                                else
 
256
                                {
 
257
                                        if(ionD->valueType != valueName)
 
258
                                        {
 
259
                                                valueName=TRANS("Mixed data");
 
260
                                                break;
 
261
                                        }
 
262
                                }
 
263
                        }
 
264
                }
 
265
        }
 
266
 
 
267
        d->xLabel=valueName;
 
268
 
 
269
 
 
270
        //Look for any ranges in input stream, and add them to the plot
 
271
        //while we are doing that, count the number of ions too
 
272
        for(unsigned int ui=0;ui<dataIn.size();ui++)
 
273
        {
 
274
                switch(dataIn[ui]->getStreamType())
 
275
                {
 
276
                        case STREAM_TYPE_RANGE:
 
277
                        {
 
278
                                const RangeStreamData *rangeD;
 
279
                                rangeD=(const RangeStreamData *)dataIn[ui];
 
280
                                for(unsigned int uj=0;uj<rangeD->rangeFile->getNumRanges();uj++)
 
281
                                {
 
282
                                        unsigned int ionId;
 
283
                                        ionId=rangeD->rangeFile->getIonID(uj);
 
284
                                        //Only append the region if both the range
 
285
                                        //and the ion are enabled
 
286
                                        if((rangeD->enabledRanges)[uj] && 
 
287
                                                (rangeD->enabledIons)[ionId])
 
288
                                        {
 
289
                                                //save the range as a "region"
 
290
                                                d->regions.push_back(rangeD->rangeFile->getRange(uj));
 
291
                                                d->regionID.push_back(uj);
 
292
                                                d->parent=this;
 
293
                                                //FIXME: Const correctness
 
294
                                                d->regionParent=(Filter*)rangeD->parent;
 
295
 
 
296
                                                RGBf colour;
 
297
                                                //Use the ionID to set the range colouring
 
298
                                                colour=rangeD->rangeFile->getColour(ionId);
 
299
 
 
300
                                                //push back the range colour
 
301
                                                d->regionR.push_back(colour.red);
 
302
                                                d->regionG.push_back(colour.green);
 
303
                                                d->regionB.push_back(colour.blue);
 
304
                                        }
 
305
                                }
 
306
                                break;
 
307
                        }
 
308
                        default:
 
309
                                break;
 
310
                }
 
311
        }
 
312
 
 
313
#pragma omp parallel for
 
314
        for(unsigned int ui=0;ui<nBins;ui++)
 
315
        {
 
316
                d->xyData[ui].first = minPlot + ui*binWidth;
 
317
                d->xyData[ui].second=0;
 
318
        }       
 
319
        //Compute the plot bounds
 
320
        d->autoSetHardBounds();
 
321
        //Limit them to 1.0 or greater (due to log)
 
322
        d->hardMinY=std::min(1.0f,d->hardMaxY);
 
323
 
 
324
 
 
325
        //Number of ions currently processed
 
326
        size_t n=0;
 
327
        unsigned int curProg=NUM_CALLBACK;
 
328
        //Loop through each type of data        
 
329
        for(unsigned int ui=0;ui<dataIn.size() ;ui++)
 
330
        {
 
331
                switch(dataIn[ui]->getStreamType())
 
332
                {
 
333
                        case STREAM_TYPE_IONS: 
 
334
                        {
 
335
                                const IonStreamData *ions;
 
336
                                ions = (const IonStreamData *)dataIn[ui];
 
337
 
 
338
 
 
339
 
 
340
                                //Sum the data bins as needed
 
341
                                for(unsigned int uj=0;uj<ions->data.size(); uj++)
 
342
                                {
 
343
                                        unsigned int bin;
 
344
                                        bin = (unsigned int)((ions->data[uj].getMassToCharge()-minPlot)/binWidth);
 
345
                                        //Dependant upon the bounds,
 
346
                                        //actual data could be anywhere.
 
347
                                        if( bin < d->xyData.size())
 
348
                                                d->xyData[bin].second++;
 
349
 
 
350
                                        //update progress every CALLBACK ions
 
351
                                        if(!curProg--)
 
352
                                        {
 
353
                                                n+=NUM_CALLBACK;
 
354
                                                progress.filterProgress= (unsigned int)(((float)(n)/((float)totalSize))*100.0f);
 
355
                                                curProg=NUM_CALLBACK;
 
356
                                                if(!(*callback)(false))
 
357
                                                {
 
358
                                                        delete d;
 
359
                                                        return SPECTRUM_ABORT_FAIL;
 
360
                                                }
 
361
                                        }
 
362
                                }
 
363
 
 
364
                                break;
 
365
                        }
 
366
                        default:
 
367
                                //Don't propagate any type.
 
368
                                break;
 
369
                }
 
370
 
 
371
        }
 
372
 
 
373
        if(cache)
 
374
        {
 
375
                d->cached=1; //IMPORTANT: cached must be set PRIOR to push back
 
376
                filterOutputs.push_back(d);
 
377
                cacheOK=true;
 
378
        }
 
379
        else
 
380
                d->cached=0;
 
381
 
 
382
        getOut.push_back(d);
 
383
 
 
384
        return 0;
 
385
}
 
386
 
 
387
void SpectrumPlotFilter::getProperties(FilterPropGroup &propertyList) const
 
388
{
 
389
 
 
390
        FilterProperty p;
 
391
        size_t curGroup=0;
 
392
        string str;
 
393
 
 
394
        stream_cast(str,binWidth);
 
395
        p.name=TRANS("Bin width");
 
396
        p.data=str;
 
397
        p.key=KEY_SPECTRUM_BINWIDTH;
 
398
        p.type=PROPERTY_TYPE_REAL;
 
399
        p.helpText=TRANS("Step size for spectrum");
 
400
        propertyList.addProperty(p,curGroup);
 
401
 
 
402
        if(autoExtrema)
 
403
                str = "1";
 
404
        else
 
405
                str = "0";
 
406
 
 
407
 
 
408
        p.name=TRANS("Auto Min/max");
 
409
        p.data=str;
 
410
        p.key=KEY_SPECTRUM_AUTOEXTREMA;
 
411
        p.type=PROPERTY_TYPE_BOOL;
 
412
        p.helpText=TRANS("Automatically compute spectrum upper and lower bound");
 
413
        propertyList.addProperty(p,curGroup);
 
414
 
 
415
        stream_cast(str,minPlot);
 
416
        p.data=str;
 
417
        p.name=TRANS("Min");
 
418
        p.key=KEY_SPECTRUM_MIN;
 
419
        p.type=PROPERTY_TYPE_REAL;
 
420
        p.helpText=TRANS("Starting position for spectrum");
 
421
        propertyList.addProperty(p,curGroup);
 
422
 
 
423
        stream_cast(str,maxPlot);
 
424
        p.key=KEY_SPECTRUM_MAX;
 
425
        p.name=TRANS("Max");
 
426
        p.data=str;
 
427
        p.type=PROPERTY_TYPE_REAL;
 
428
        p.helpText=TRANS("Ending position for spectrum");
 
429
        propertyList.addProperty(p,curGroup);
 
430
        
 
431
        if(logarithmic)
 
432
                str = "1";
 
433
        else
 
434
                str = "0";
 
435
        p.key=KEY_SPECTRUM_LOGARITHMIC;
 
436
        p.name=TRANS("Logarithmic");
 
437
        p.data=str;
 
438
        p.type=PROPERTY_TYPE_BOOL;
 
439
        p.helpText=TRANS("Convert the plot to logarithmic mode");
 
440
        propertyList.addProperty(p,curGroup);
 
441
 
 
442
        //Let the user know what the valid values for plot type are
 
443
        vector<pair<unsigned int,string> > choices;
 
444
 
 
445
 
 
446
        string tmpStr;
 
447
        tmpStr=plotString(PLOT_TRACE_LINES);
 
448
        choices.push_back(make_pair((unsigned int) PLOT_TRACE_LINES,tmpStr));
 
449
        tmpStr=plotString(PLOT_TRACE_BARS);
 
450
        choices.push_back(make_pair((unsigned int)PLOT_TRACE_BARS,tmpStr));
 
451
        tmpStr=plotString(PLOT_TRACE_STEPS);
 
452
        choices.push_back(make_pair((unsigned int)PLOT_TRACE_STEPS,tmpStr));
 
453
        tmpStr=plotString(PLOT_TRACE_STEM);
 
454
        choices.push_back(make_pair((unsigned int)PLOT_TRACE_STEM,tmpStr));
 
455
 
 
456
 
 
457
        tmpStr= choiceString(choices,plotStyle);
 
458
        p.name=TRANS("Plot Type");
 
459
        p.data=tmpStr;
 
460
        p.type=PROPERTY_TYPE_CHOICE;
 
461
        p.helpText=TRANS("Visual style of plot");
 
462
        p.key=KEY_SPECTRUM_PLOTTYPE;
 
463
        propertyList.addProperty(p,curGroup);
 
464
 
 
465
        string thisCol;
 
466
 
 
467
        //Convert the colour to a hex string
 
468
        genColString((unsigned char)(r*255.0),(unsigned char)(g*255.0),
 
469
                (unsigned char)(b*255.0),(unsigned char)(a*255.0),thisCol);
 
470
 
 
471
        p.name=TRANS("Colour");
 
472
        p.data=thisCol; 
 
473
        p.type=PROPERTY_TYPE_COLOUR;
 
474
        p.helpText=TRANS("Colour of plotted spectrum");
 
475
        p.key=KEY_SPECTRUM_COLOUR;
 
476
        propertyList.addProperty(p,curGroup);
 
477
}
 
478
 
 
479
bool SpectrumPlotFilter::setProperty( unsigned int key, 
 
480
                                        const std::string &value, bool &needUpdate) 
 
481
{
 
482
        needUpdate=false;
 
483
        switch(key)
 
484
        {
 
485
                //Bin width
 
486
                case KEY_SPECTRUM_BINWIDTH:
 
487
                {
 
488
                        float newWidth;
 
489
                        if(stream_cast(newWidth,value))
 
490
                                return false;
 
491
 
 
492
                        if(newWidth < std::numeric_limits<float>::epsilon())
 
493
                                return false;
 
494
 
 
495
                        //Prevent overflow on next line
 
496
                        if(maxPlot == std::numeric_limits<float>::max() ||
 
497
                                minPlot == std::numeric_limits<float>::min())
 
498
                                return false;
 
499
 
 
500
                        if(newWidth < 0.0f || newWidth > (maxPlot - minPlot))
 
501
                                return false;
 
502
 
 
503
 
 
504
 
 
505
                        needUpdate=true;
 
506
                        binWidth=newWidth;
 
507
                        clearCache();
 
508
 
 
509
                        break;
 
510
                }
 
511
                //Auto min/max
 
512
                case KEY_SPECTRUM_AUTOEXTREMA:
 
513
                {
 
514
                        //Only allow valid values
 
515
                        unsigned int valueInt;
 
516
                        if(stream_cast(valueInt,value))
 
517
                                return false;
 
518
 
 
519
                        //Only update as needed
 
520
                        if(valueInt ==0 || valueInt == 1)
 
521
                        {
 
522
                                if((int)autoExtrema != valueInt)
 
523
                                {
 
524
                                        needUpdate=true;
 
525
                                        autoExtrema=valueInt;
 
526
                                }
 
527
                                else
 
528
                                        needUpdate=false;
 
529
 
 
530
                        }
 
531
                        else
 
532
                                return false;           
 
533
        
 
534
                        clearCache();
 
535
        
 
536
                        break;
 
537
 
 
538
                }
 
539
                //Plot min
 
540
                case KEY_SPECTRUM_MIN:
 
541
                {
 
542
                        if(autoExtrema)
 
543
                                return false;
 
544
 
 
545
                        float newMin;
 
546
                        if(stream_cast(newMin,value))
 
547
                                return false;
 
548
 
 
549
                        if(newMin >= maxPlot)
 
550
                                return false;
 
551
 
 
552
                        needUpdate=true;
 
553
                        minPlot=newMin;
 
554
 
 
555
                        clearCache();
 
556
                        break;
 
557
                }
 
558
                //Plot max
 
559
                case KEY_SPECTRUM_MAX:
 
560
                {
 
561
                        if(autoExtrema)
 
562
                                return false;
 
563
                        float newMax;
 
564
                        if(stream_cast(newMax,value))
 
565
                                return false;
 
566
 
 
567
                        if(newMax <= minPlot)
 
568
                                return false;
 
569
 
 
570
                        needUpdate=true;
 
571
                        maxPlot=newMax;
 
572
                        clearCache();
 
573
 
 
574
                        break;
 
575
                }
 
576
                case KEY_SPECTRUM_LOGARITHMIC:
 
577
                {
 
578
                        //Only allow valid values
 
579
                        unsigned int valueInt;
 
580
                        if(stream_cast(valueInt,value))
 
581
                                return false;
 
582
 
 
583
                        //Only update as needed
 
584
                        if(valueInt ==0 || valueInt == 1)
 
585
                        {
 
586
                                if((int)logarithmic != valueInt)
 
587
                                {
 
588
                                        needUpdate=true;
 
589
                                        logarithmic=valueInt;
 
590
                                }
 
591
                                else
 
592
                                        needUpdate=false;
 
593
 
 
594
                        }
 
595
                        else
 
596
                                return false;           
 
597
                        
 
598
                        if(cacheOK)
 
599
                        {
 
600
                                //Change the output of the plot streams that
 
601
                                //we cached, in order to avoid recomputation
 
602
                                for(size_t ui=0;ui<filterOutputs.size();ui++)
 
603
                                {
 
604
                                        if(filterOutputs[ui]->getStreamType() == STREAM_TYPE_PLOT)
 
605
                                        {
 
606
                                                PlotStreamData *p;
 
607
                                                p =(PlotStreamData*)filterOutputs[ui];
 
608
 
 
609
                                                p->logarithmic=logarithmic;
 
610
                                        }
 
611
                                }
 
612
 
 
613
                        }
 
614
        
 
615
                        break;
 
616
 
 
617
                }
 
618
                //Plot type
 
619
                case KEY_SPECTRUM_PLOTTYPE:
 
620
                {
 
621
                        unsigned int tmpPlotType;
 
622
 
 
623
                        tmpPlotType=plotID(value);
 
624
 
 
625
                        if(tmpPlotType >= PLOT_TRACE_ENDOFENUM)
 
626
                                return false;
 
627
 
 
628
                        plotStyle = tmpPlotType;
 
629
                        needUpdate=true;        
 
630
 
 
631
 
 
632
                        //Perform introspection on 
 
633
                        //cache
 
634
                        if(cacheOK)
 
635
                        {
 
636
                                for(size_t ui=0;ui<filterOutputs.size();ui++)
 
637
                                {
 
638
                                        if(filterOutputs[ui]->getStreamType() == STREAM_TYPE_PLOT)
 
639
                                        {
 
640
                                                PlotStreamData *p;
 
641
                                                p =(PlotStreamData*)filterOutputs[ui];
 
642
 
 
643
                                                p->plotStyle=plotStyle;
 
644
                                        }
 
645
                                }
 
646
 
 
647
                        }
 
648
 
 
649
                        break;
 
650
                }
 
651
                case KEY_SPECTRUM_COLOUR:
 
652
                {
 
653
                        unsigned char newR,newG,newB,newA;
 
654
 
 
655
                        parseColString(value,newR,newG,newB,newA);
 
656
 
 
657
                        if(newB != b || newR != r ||
 
658
                                newG !=g || newA != a)
 
659
                                needUpdate=true;
 
660
                        r=newR/255.0;
 
661
                        g=newG/255.0;
 
662
                        b=newB/255.0;
 
663
                        a=newA/255.0;
 
664
                        if(cacheOK)
 
665
                        {
 
666
                                for(size_t ui=0;ui<filterOutputs.size();ui++)
 
667
                                {
 
668
                                        if(filterOutputs[ui]->getStreamType() == STREAM_TYPE_PLOT)
 
669
                                        {
 
670
                                                PlotStreamData *p;
 
671
                                                p =(PlotStreamData*)filterOutputs[ui];
 
672
 
 
673
                                                p->r=r;
 
674
                                                p->g=g;
 
675
                                                p->b=b;
 
676
                                        }
 
677
                                }
 
678
 
 
679
                        }
 
680
                        break;
 
681
                }
 
682
                default:
 
683
                        ASSERT(false);
 
684
                        break;
 
685
 
 
686
        }
 
687
 
 
688
        
 
689
        return true;
 
690
}
 
691
 
 
692
void SpectrumPlotFilter::setUserString(const std::string &s)
 
693
{
 
694
        if(userString !=s)
 
695
        {
 
696
                userString=s;
 
697
                clearCache();
 
698
                cacheOK=false;
 
699
        }
 
700
}
 
701
 
 
702
 
 
703
std::string  SpectrumPlotFilter::getErrString(unsigned int code) const
 
704
{
 
705
        switch(code)
 
706
        {
 
707
                case SPECTRUM_BAD_ALLOC:
 
708
                        return string(TRANS("Insufficient memory for spectrum filter."));
 
709
                case SPECTRUM_BAD_BINCOUNT:
 
710
                        return string(TRANS("Bad bincount value in spectrum filter."));
 
711
        }
 
712
        return std::string("BUG: (SpectrumPlotFilter::getErrString) Shouldn't see this!");
 
713
}
 
714
 
 
715
void SpectrumPlotFilter::setPropFromBinding(const SelectionBinding &b)
 
716
{
 
717
        ASSERT(false);
 
718
}
 
719
 
 
720
bool SpectrumPlotFilter::writeState(std::ostream &f,unsigned int format, unsigned int depth) const
 
721
{
 
722
        using std::endl;
 
723
        switch(format)
 
724
        {
 
725
                case STATE_FORMAT_XML:
 
726
                {       
 
727
                        f << tabs(depth) << "<"  << trueName() << ">" << endl;
 
728
                        f << tabs(depth+1) << "<userstring value=\""<< escapeXML(userString) << "\"/>"  << endl;
 
729
 
 
730
                        f << tabs(depth+1) << "<extrema min=\"" << minPlot << "\" max=\"" <<
 
731
                                        maxPlot  << "\" auto=\"" << autoExtrema << "\"/>" << endl;
 
732
                        f << tabs(depth+1) << "<binwidth value=\"" << binWidth<< "\"/>" << endl;
 
733
 
 
734
                        f << tabs(depth+1) << "<colour r=\"" <<  r<< "\" g=\"" << g << "\" b=\"" <<b
 
735
                                << "\" a=\"" << a << "\"/>" <<endl;
 
736
                        
 
737
                        f << tabs(depth+1) << "<logarithmic value=\"" << logarithmic<< "\"/>" << endl;
 
738
 
 
739
                        f << tabs(depth+1) << "<plottype value=\"" << plotStyle<< "\"/>" << endl;
 
740
                        
 
741
                        f << tabs(depth) << "</" << trueName() <<  ">" << endl;
 
742
                        break;
 
743
                }
 
744
                default:
 
745
                        ASSERT(false);
 
746
                        return false;
 
747
        }
 
748
 
 
749
        return true;
 
750
}
 
751
 
 
752
bool SpectrumPlotFilter::readState(xmlNodePtr &nodePtr, const std::string &stateFileDir)
 
753
{
 
754
        using std::string;
 
755
        string tmpStr;
 
756
 
 
757
        //Retrieve user string
 
758
        //===
 
759
        if(XMLHelpFwdToElem(nodePtr,"userstring"))
 
760
                return false;
 
761
 
 
762
        xmlChar *xmlString=xmlGetProp(nodePtr,(const xmlChar *)"value");
 
763
        if(!xmlString)
 
764
                return false;
 
765
        userString=(char *)xmlString;
 
766
        xmlFree(xmlString);
 
767
        //===
 
768
 
 
769
        //Retrieve Extrema 
 
770
        //===
 
771
        float tmpMin,tmpMax;
 
772
        if(XMLHelpFwdToElem(nodePtr,"extrema"))
 
773
                return false;
 
774
 
 
775
        xmlString=xmlGetProp(nodePtr,(const xmlChar *)"min");
 
776
        if(!xmlString)
 
777
                return false;
 
778
        tmpStr=(char *)xmlString;
 
779
        xmlFree(xmlString);
 
780
 
 
781
        //convert from string to digit
 
782
        if(stream_cast(tmpMin,tmpStr))
 
783
                return false;
 
784
 
 
785
        xmlString=xmlGetProp(nodePtr,(const xmlChar *)"max");
 
786
        if(!xmlString)
 
787
                return false;
 
788
        tmpStr=(char *)xmlString;
 
789
        xmlFree(xmlString);
 
790
        
 
791
        //convert from string to digit
 
792
        if(stream_cast(tmpMax,tmpStr))
 
793
                return false;
 
794
 
 
795
 
 
796
        if(tmpMin >=tmpMax)
 
797
                return false;
 
798
 
 
799
        minPlot=tmpMin;
 
800
        maxPlot=tmpMax;
 
801
 
 
802
        xmlString=xmlGetProp(nodePtr,(const xmlChar *)"auto");
 
803
        if(!xmlString)
 
804
                return false;
 
805
        
 
806
        tmpStr=(char *)xmlString;
 
807
        if(tmpStr == "1") 
 
808
                autoExtrema=true;
 
809
        else if(tmpStr== "0")
 
810
                autoExtrema=false;
 
811
        else
 
812
        {
 
813
                xmlFree(xmlString);
 
814
                return false;
 
815
        }
 
816
 
 
817
        xmlFree(xmlString);
 
818
        //===
 
819
        
 
820
        //Retrieve bin width 
 
821
        //====
 
822
        //
 
823
        if(!XMLGetNextElemAttrib(nodePtr,binWidth,"binwidth","value"))
 
824
                return false;
 
825
        if(binWidth  <= 0.0)
 
826
                return false;
 
827
 
 
828
        if(!autoExtrema && binWidth > maxPlot - minPlot)
 
829
                return false;
 
830
        //====
 
831
        //Retrieve colour
 
832
        //====
 
833
        if(XMLHelpFwdToElem(nodePtr,"colour"))
 
834
                return false;
 
835
        if(!parseXMLColour(nodePtr,r,g,b,a))
 
836
                return false;
 
837
        //====
 
838
        
 
839
        //Retrieve logarithmic mode
 
840
        //====
 
841
        if(!XMLGetNextElemAttrib(nodePtr,tmpStr,"logarithmic","value"))
 
842
                return false;
 
843
        if(tmpStr == "0")
 
844
                logarithmic=false;
 
845
        else if(tmpStr == "1")
 
846
                logarithmic=true;
 
847
        else
 
848
                return false;
 
849
        //====
 
850
 
 
851
        //Retrieve plot type 
 
852
        //====
 
853
        if(!XMLGetNextElemAttrib(nodePtr,plotStyle,"plottype","value"))
 
854
                return false;
 
855
        if(plotStyle >= PLOT_TRACE_ENDOFENUM)
 
856
               return false;    
 
857
        //====
 
858
 
 
859
        return true;
 
860
}
 
861
 
 
862
unsigned int SpectrumPlotFilter::getRefreshBlockMask() const
 
863
{
 
864
        //Absolutely nothing can go through this filter.
 
865
        return STREAMTYPE_MASK_ALL;
 
866
}
 
867
 
 
868
unsigned int SpectrumPlotFilter::getRefreshEmitMask() const
 
869
{
 
870
        return STREAM_TYPE_PLOT;
 
871
}
 
872
 
 
873
unsigned int SpectrumPlotFilter::getRefreshUseMask() const
 
874
{
 
875
        return STREAM_TYPE_IONS;
 
876
}
 
877
 
 
878
#ifdef DEBUG
 
879
#include <memory>
 
880
 
 
881
IonStreamData *synDataPoints(const unsigned int span[], unsigned int numPts)
 
882
{
 
883
        IonStreamData *d = new IonStreamData;
 
884
        
 
885
        for(unsigned int ui=0;ui<numPts;ui++)
 
886
        {
 
887
                IonHit h;
 
888
                h.setPos(Point3D(ui%span[0],
 
889
                        ui%span[1],ui%span[2]));
 
890
                h.setMassToCharge(ui);
 
891
                d->data.push_back(h);
 
892
        }
 
893
 
 
894
        return d;
 
895
}
 
896
 
 
897
bool countTest()
 
898
{
 
899
        auto_ptr<IonStreamData> d;
 
900
        const unsigned int VOL[]={
 
901
                                10,10,10
 
902
                                };
 
903
        const unsigned int NUMPTS=100;
 
904
        d.reset(synDataPoints(VOL,NUMPTS));
 
905
 
 
906
        SpectrumPlotFilter *f;
 
907
        f = new SpectrumPlotFilter;
 
908
 
 
909
 
 
910
        bool needUp;
 
911
        std::string s;
 
912
        TEST(f->setProperty(KEY_SPECTRUM_LOGARITHMIC,"0",needUp),"Set prop");
 
913
        
 
914
        genColString(255,0,0,s);
 
915
        TEST(f->setProperty(KEY_SPECTRUM_COLOUR,s,needUp),"Set prop");
 
916
 
 
917
        vector<const FilterStreamData*> streamIn,streamOut;
 
918
 
 
919
        streamIn.push_back(d.get());
 
920
 
 
921
        //OK, so now do the rotation
 
922
        //Do the refresh
 
923
        ProgressData p;
 
924
        f->setCaching(false);
 
925
        TEST(!f->refresh(streamIn,streamOut,p,dummyCallback),"refresh error code");
 
926
        delete f;
 
927
        
 
928
        TEST(streamOut.size() == 1,"stream count");
 
929
        TEST(streamOut[0]->getStreamType() == STREAM_TYPE_PLOT,"stream type");
 
930
 
 
931
        PlotStreamData *plot;
 
932
        plot = (PlotStreamData*)streamOut[0];
 
933
 
 
934
        
 
935
        //Check the plot colour is what we want.
 
936
        TEST(fabs(plot->r -1.0f) < sqrt(std::numeric_limits<float>::epsilon()),"colour (r)");
 
937
        TEST(plot->g< 
 
938
                sqrt(std::numeric_limits<float>::epsilon()),"colour (g)");
 
939
        TEST(plot->b < sqrt(std::numeric_limits<float>::epsilon()),"colour (b)");
 
940
 
 
941
        //Count the number of ions in the plot, and check that it is equal to the number of ions we put in.
 
942
        float sumV=0;
 
943
        
 
944
        for(unsigned int ui=0;ui<plot->xyData.size();ui++)
 
945
                sumV+=plot->xyData[ui].second;
 
946
 
 
947
        TEST(fabs(sumV - (float)NUMPTS) < 
 
948
                std::numeric_limits<float>::epsilon(),"ion count");
 
949
 
 
950
 
 
951
        delete plot;
 
952
        return true;
 
953
}
 
954
 
 
955
bool SpectrumPlotFilter::runUnitTests() 
 
956
{
 
957
        if(!countTest())
 
958
                return false;
 
959
 
 
960
        return true;
 
961
}
 
962
 
 
963
#endif
 
964