diff -r bcb9acfa66de -r effd078610a7 docs/manual-latex/build-latex.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ docs/manual-latex/build-latex.sh Tue Jun 21 12:45:20 2016 +0100
@@ -0,0 +1,37 @@
+#!/bin/bash
+LATEXBIN=pdflatex
+BIBTEXBIN=bibtex
+if [ x`which $LATEXBIN` == x"" ] ; then
+ echo "no $LATEXBIN"
+ exit 1
+fi
+
+if [ x`which $BIBTEXBIN` == x"" ] ; then
+ echo "no $BIBTEXBIN"
+ exit 1
+fi
+
+MANUAL=manual.tex
+
+#check to see if the manual and its bib file are around
+if [ ! -f $MANUAL ] ; then
+ echo "$MANUAL is missing"
+ exit 1
+fi
+
+#Remove the old manul
+rm -f manual.pdf
+
+
+
+#run the multi-pass latex build.
+$LATEXBIN $MANUAL || { echo "failed latex build (pass 1 of 2)"; exit 1 ; }
+$BIBTEXBIN `basename -s .tex $MANUAL` || { echo "failed bibtex build"; exit 1 ; }
+$LATEXBIN $MANUAL || { echo "failed latex build (pass 2 of 2)"; exit 1 ; }
+
+
+if [ ! -f manual.pdf ] ; then
+ echo "latex ran, but somehow we did not output the PDF...."
+ exit 1
+fi
+
diff -r bcb9acfa66de -r effd078610a7 src/backend/filter.cpp
--- src/backend/filter.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filter.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -553,7 +553,7 @@
ASSERT(scatterIntensity.empty());
- ASSERT(plotType < PLOT_TYPE_ENUM_END);
+ ASSERT(plotStyle < PLOT_TYPE_ENUM_END);
}
void RangeStreamData::checkSelfConsistent() const
{
diff -r bcb9acfa66de -r effd078610a7 src/backend/filter.h
--- src/backend/filter.h Tue May 31 13:04:58 2016 +1000
+++ src/backend/filter.h Tue Jun 21 12:45:20 2016 +0100
@@ -395,7 +395,7 @@
//Label for X, Y axes
std::string xLabel,yLabel;
- unsigned int plotType;
+ unsigned int plotStyle;
//!Structured XY data pairs for plotting curve
Array2D<float> xyData;
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/algorithms/rdf.cpp
--- src/backend/filters/algorithms/rdf.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/algorithms/rdf.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -862,6 +862,8 @@
return RDF_ABORT_FAIL;
#endif
+ *progressPtr=100;
+
return 0;
}
@@ -1003,6 +1005,8 @@
#endif
//Calculations complete!
+ *progressPtr=100;
+
return 0;
}
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/annotation.cpp
--- src/backend/filters/annotation.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/annotation.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -167,8 +167,15 @@
//If we are not enabled, do not draw anything into the output
if(!active)
+ {
+ progress.filterProgress=100;
return 0;
+ }
+ progress.step=1;
+ progress.maxStep=1;
+ progress.stepName=TRANS("Draw");
+
DrawStreamData *d;
d = new DrawStreamData;
d->parent=this;
@@ -505,6 +512,7 @@
d->cached=0;
getOut.push_back(d);
+ progress.filterProgress=100;
return 0;
}
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/boundingBox.cpp
--- src/backend/filters/boundingBox.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/boundingBox.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -510,7 +510,6 @@
}
#endif
bTotal.expand(bThis);
- progress.filterProgress=100;
break;
}
default:
@@ -521,6 +520,7 @@
getOut.push_back(dataIn[ui]);
}
+ progress.filterProgress=100;
//Append the bounding box if it is valid
if(bTotal.isValid())
{
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/clusterAnalysis.cpp
--- src/backend/filters/clusterAnalysis.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/clusterAnalysis.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -685,7 +685,7 @@
Plot2DStreamData *p = new Plot2DStreamData;
p->parent=this;
- p->plotType=PLOT_2D_SCATTER;
+ p->plotStyle=PLOT_2D_SCATTER;
p->dataLabel=TRANS("Morphology Plot");
p->xLabel=TRANS("\\lambda_1:\\lambda_2 ratio");
p->yLabel=TRANS("\\lambda_2:\\lambda_3 ratio");
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/ionColour.cpp
--- src/backend/filters/ionColour.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/ionColour.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -271,12 +271,14 @@
p.name=TRANS("Show Bar");
+ p.helpText=TRANS("Display the colour legend in the 3D view");
p.key=KEY_IONCOLOURFILTER_SHOWBAR;
p.data=boolStrEnc(showColourBar);
p.type=PROPERTY_TYPE_BOOL;
propertyList.addProperty(p,curGroup);
p.name=TRANS("Opacity");
+ p.helpText=TRANS("How see-through to make the legend (0- transparent, 1- solid)");
p.key=KEY_IONCOLOURFILTER_ALPHA;
stream_cast(p.data,alpha);
p.type=PROPERTY_TYPE_REAL;
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/ionDownsample.cpp
--- src/backend/filters/ionDownsample.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/ionDownsample.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -88,7 +88,7 @@
rsdIncoming = new RangeStreamData;
*rsdIncoming=*c;
- if(ionFractions.size() != c->rangeFile->getNumIons())
+ if(ionFractions.size() != c->rangeFile->getNumIons()+1)
{
//set up some defaults; seeded from normal
ionFractions.resize(c->rangeFile->getNumIons()+1,fraction);
@@ -464,7 +464,8 @@
propertyList.setGroupTitle(curGroup,TRANS("Mode"));
curGroup++;
- if(rsdIncoming && perSpecies)
+
+ if(rsdIncoming && perSpecies && rsdIncoming->enabledIons.size())
{
unsigned int typeVal;
if(fixedNumOut)
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/ionInfo.cpp
--- src/backend/filters/ionInfo.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/ionInfo.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -398,7 +398,7 @@
//"Pairwise events" - where we perform an action if both
- //These
+ //these are set
if(wantIonCounts && wantVolume)
{
if(computedVol > sqrtf(std::numeric_limits<float>::epsilon()))
@@ -420,6 +420,9 @@
}
}
+
+ progress.filterProgress=100;
+
return 0;
}
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/spatialAnalysis.cpp
--- src/backend/filters/spatialAnalysis.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/spatialAnalysis.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -655,115 +655,180 @@
return ERR_FILE_READ_FAIL;
-
- progress.step=3;
- progress.stepName=TRANS("Build");
- progress.filterProgress=0;
-
- //Build the search tree we will use to perform replacement
- K3DTreeMk2 tree;
- tree.resetPts(fileIons,false);
- if(!tree.build())
- return ERR_ABORT_FAIL;
- BoundCube b;
- tree.getBoundCube(b);
-
- //map the offset of the nearest to
- //the tree ID
- vector<size_t > nearestVec;
- nearestVec.resize(inIons.size());
-
- //TODO: pair vector might be faster
- // as we can use it in sequence, and can use openmp
- map<size_t,size_t> matchedMap;
-
- //Find the nearest point for all points in the dataset
-
- #pragma omp parallel for
- for(size_t ui=0;ui<inIons.size();ui++)
+ vector<IonHit> outIons;
+ if(inIons.empty() || fileIons.empty())
{
- nearestVec[ui]=tree.findNearestUntagged(inIons[ui].getPos(),b,false);
- }
-
- float sqrReplaceTol=replaceTolerance*replaceTolerance;
-
- //Filter this to only points that had an NN within range
- #pragma omp parallel for
- for(size_t ui=0;ui<inIons.size();ui++)
- {
- if(nearestVec[ui]!=(size_t)-1 && inIons[ui].getPos().sqrDist(*tree.getPt(nearestVec[ui])) <=sqrReplaceTol)
+ //Performance increase if we have an empty item.
+ // - in this case we can swap sets around
+ switch(replaceMode)
{
- #pragma omp critical
- matchedMap[ui]=tree.getOrigIndex(nearestVec[ui]);
+ case REPLACE_MODE_UNION:
+ {
+ //If the local data is empty, then the union is just the "b" data (swap).
+ // if nonempty, then it is simply the "a" data
+ if(inIons.empty())
+ outIons.swap(fileIons);
+ else
+ outIons.swap(inIons);
+ break;
+ }
+ case REPLACE_MODE_SUBTRACT:
+ {
+ //if either localdata OR bdata is empty, then we don't need to do anything.
+ // either way, input stays as it is
+ outIons.swap(inIons);
+ break;
+ }
+ case REPLACE_MODE_INTERSECT:
+ {
+ //intersection with empty set is empty set.
+ // might as well clear the ions incoming
+ inIons.clear();
+ break;
+ }
+ default:
+ ASSERT(false);
+
}
}
-
- nearestVec.clear();
-
-
- progress.step=4;
- progress.stepName=TRANS("Compute");
- progress.filterProgress=0;
-
- //Finish if no matches
- if(matchedMap.empty())
+ else
{
- progress.filterProgress=100;
- return 0;
- }
-
- vector<IonHit> outIons;
- switch(replaceMode)
- {
- case REPLACE_MODE_SUBTRACT:
+
+ progress.step=3;
+ progress.stepName=TRANS("Build");
+ progress.filterProgress=0;
+
+ //TODO: Possible speed increase by finding the smaller of
+ // the two inputs, and using that to build the tree
+
+ //Build the search tree we will use to perform replacement
+ K3DTreeMk2 tree;
+ tree.resetPts(fileIons,false);
+ if(!tree.build())
+ return ERR_ABORT_FAIL;
+ BoundCube b;
+ tree.getBoundCube(b);
+
+ //map the offset of the nearest to
+ //the tree ID
+ vector<size_t > nearestVec;
+ nearestVec.resize(inIons.size());
+
+ //TODO: pair vector might be faster
+ // as we can use it in sequence, and can use openmp
+ map<size_t,size_t> matchedMap;
+
+ //Find the nearest point for all points in the dataset
+ // maps the ith ion in "inions" to the tree value
+ #pragma omp parallel for
+ for(size_t ui=0;ui<inIons.size();ui++)
{
- //In subtraction mode, we should have
- // at least this many ions
- if(inIons.size() > matchedMap.size())
- outIons.reserve(inIons.size()-matchedMap.size());
-
- //
- #pragma omp parallel for
- for(unsigned int ui=0;ui<inIons.size();ui++)
+ nearestVec[ui]=tree.findNearestUntagged(inIons[ui].getPos(),b,false);
+ }
+
+ float sqrReplaceTol=replaceTolerance*replaceTolerance;
+
+ //Filter this to only points that had an NN within range
+ #pragma omp parallel for
+ for(size_t ui=0;ui<inIons.size();ui++)
+ {
+ if(nearestVec[ui]!=(size_t)-1 && inIons[ui].getPos().sqrDist(*tree.getPt(nearestVec[ui])) <=sqrReplaceTol)
{
- map<size_t,size_t>::iterator it;
- it=matchedMap.find(ui);
- if(it != matchedMap.end())
- continue;
-
#pragma omp critical
- outIons.push_back(inIons[ui]);
+ matchedMap[ui]=tree.getOrigIndex(nearestVec[ui]);
}
- break;
}
- case REPLACE_MODE_INTERSECT:
+
+ nearestVec.clear();
+
+
+ progress.step=4;
+ progress.stepName=TRANS("Compute");
+ progress.filterProgress=0;
+
+
+ //now we have a map that matches as so:
+ // map ( "inIon" ID -> "fileIon" ID)
+ // inIon should be our "A" in "A operator B"
+ switch(replaceMode)
{
- outIons.reserve(matchedMap.size());
-
- if(replaceMass)
+ case REPLACE_MODE_SUBTRACT:
{
- for(map<size_t,size_t>::const_iterator it=matchedMap.begin();it!=matchedMap.end();++it)
+ //If no matches, A-0 = A. Just return input
+ if(matchedMap.empty())
{
- outIons.push_back(fileIons[it->second]);
- ASSERT(fileIons[it->second].getPosRef().sqrDist(inIons[it->first].getPosRef()) < sqrReplaceTol);
+ outIons.swap(inIons);
+ break;
}
+ //In subtraction mode, we should have
+ // at least this many ions
+ if(inIons.size() > matchedMap.size())
+ outIons.reserve(inIons.size()-matchedMap.size());
+
+ //
+ #pragma omp parallel for
+ for(unsigned int ui=0;ui<inIons.size();ui++)
+ {
+ map<size_t,size_t>::iterator it;
+ it=matchedMap.find(ui);
+ if(it != matchedMap.end())
+ continue;
+
+ #pragma omp critical
+ outIons.push_back(inIons[ui]);
+ }
+ break;
}
- else
+ case REPLACE_MODE_INTERSECT:
{
- for(map<size_t,size_t>::const_iterator it=matchedMap.begin();it!=matchedMap.end();++it)
+ //Finish if no matches
+ if(matchedMap.empty())
+ break;
+
+ outIons.reserve(matchedMap.size());
+
+ if(replaceMass)
{
- outIons.push_back(inIons[it->first]);
+ for(map<size_t,size_t>::const_iterator it=matchedMap.begin();it!=matchedMap.end();++it)
+ {
+ outIons.push_back(fileIons[it->second]);
+ ASSERT(fileIons[it->second].getPosRef().sqrDist(inIons[it->first].getPosRef()) < sqrReplaceTol);
+ }
}
+ else
+ {
+ for(map<size_t,size_t>::const_iterator it=matchedMap.begin();it!=matchedMap.end();++it)
+ {
+ outIons.push_back(inIons[it->first]);
+ }
+ }
+ break;
}
- break;
+ case REPLACE_MODE_UNION:
+ {
+ outIons.swap(fileIons);
+ outIons.reserve(outIons.size() + fileIons.size() - matchedMap.size());
+ map<size_t,size_t>::const_iterator it=matchedMap.begin();
+
+
+ for(unsigned int ui=0;ui<inIons.size();ui++)
+ {
+ if(it !=matchedMap.end() && (it->first == ui) )
+ {
+ it++;
+ continue;
+ }
+
+
+ outIons.push_back(inIons[ui]);
+ }
+
+
+ break;
+ }
+ default:
+ ASSERT(false);
}
- case REPLACE_MODE_UNION:
- {
- ASSERT(false);
- break;
- }
- default:
- ASSERT(false);
}
//Only output ions if any were found
@@ -2779,6 +2844,8 @@
newD->data.resize(d->data.size());
if(stopMode == STOP_MODE_NEIGHBOUR)
{
+ unsigned int nProg=0;
+
bool spin=false;
#pragma omp parallel for shared(spin)
for(size_t uj=0;uj<d->data.size();uj++)
@@ -2811,14 +2878,15 @@
}
res.clear();
+ #pragma atomic
+ nProg++;
//Update progress as needed
if(!curProg--)
{
#pragma omp critical
{
- n+=NUM_CALLBACK/(nnMax);
- progress.filterProgress= (unsigned int)(((float)n/(float)totalDataSize)*100.0f);
+ progress.filterProgress= (unsigned int)(((float)nProg/(float)totalDataSize)*100.0f);
if(*Filter::wantAbort)
spin=true;
curProg=NUM_CALLBACK/(nnMax);
@@ -3063,9 +3131,10 @@
IonStreamData *newD = new IonStreamData;
newD->parent=this;
- //Adjust this number to provide more update thanusual, because we
+ //Adjust this number to provide more update than usual, because we
//are not doing an o(1) task between updates; yes, it is a hack
- unsigned int curProg=NUM_CALLBACK/(10*nnMax);
+ const unsigned int PROG_PER_PASS=NUM_CALLBACK/(10*nnMax);
+ unsigned int curProg=PROG_PER_PASS;
newD->data.reserve(d->data.size());
if(stopMode == STOP_MODE_NEIGHBOUR)
{
@@ -3113,11 +3182,11 @@
{
#pragma omp critical
{
- n+=NUM_CALLBACK/(nnMax);
+ n+=PROG_PER_PASS;
progress.filterProgress= (unsigned int)(((float)n/(float)totalDataSize)*100.0f);
if(*Filter::wantAbort)
spin=true;
- curProg=NUM_CALLBACK/(nnMax);
+ curProg=PROG_PER_PASS;
}
}
}
@@ -3263,6 +3332,8 @@
break;
}
}
+ progress.filterProgress=100;
+
//If we have bad points, let the user know.
if(!badPts.empty())
{
@@ -4230,11 +4301,8 @@
}
//distance between search pt and found pt
- float sqrDistance;
- sqrDistance = searchTree.getPtRef(ptIdx).sqrDist(pSource[ui].getPosRef());
-
- if(sqrDistance > DISTANCE_EPSILON)
- ptsFound.insert(ptIdx);
+
+ ptsFound.insert(ptIdx);
}
@@ -4244,8 +4312,14 @@
//Count the number of numerator and denominator ions, using the masses we set aside earlier
for(set<size_t>::iterator it=ptsFound.begin(); it!=ptsFound.end(); ++it)
{
+
+ //check that the distance is non-zero, to force no self-matching
+ float sqrDistance;
+ sqrDistance = searchTree.getPtRef(*it).sqrDist(pSource[ui].getPosRef());
+ if(sqrDistance < DISTANCE_EPSILON)
+ continue;
+
float ionMass;
- //check that the distance is non-zero, to force no self-matching
ionMass = dataMasses[searchTree.getOrigIndex(*it)];
unsigned int ionID;
@@ -4326,9 +4400,11 @@
bool nnHistogramTest();
bool rdfPlotTest();
bool axialDistTest();
-bool replaceTest();
+bool replaceIntersectAndUnionTest();
bool localConcTestRadius();
bool localConcTestNN();
+bool replaceSubtractTest();
+bool replaceUnionTest();
bool SpatialAnalysisFilter::runUnitTests()
{
@@ -4343,8 +4419,15 @@
if(!axialDistTest())
return false;
- if(!replaceTest())
+ if(!replaceIntersectAndUnionTest())
return false;
+
+ if(!replaceSubtractTest())
+ return false;
+
+ if(!replaceUnionTest())
+ return false;
+
if(!localConcTestRadius())
return false;
@@ -4617,7 +4700,7 @@
return true;
}
-bool replaceTest()
+bool replaceIntersectAndUnionTest()
{
std::string ionFile=createTmpFilename(NULL,".pos");
@@ -4637,6 +4720,157 @@
//Create a spatial analysis filter
SpatialAnalysisFilter *f=new SpatialAnalysisFilter;
f->setCaching(false);
+ //Set it to do a union calculation
+ bool needUp;
+ string s;
+ s=TRANS(SPATIAL_ALGORITHMS[ALGORITHM_REPLACE]);
+ TEST(f->setProperty(KEY_ALGORITHM,s,needUp),"Set prop");
+ TEST(f->setProperty(KEY_REPLACE_FILE,ionFile,needUp),"Set prop");
+ s="1";
+ TEST(f->setProperty(KEY_REPLACE_VALUE,s,needUp),"Set prop");
+
+ vector<unsigned int> opVec;
+ opVec.push_back(REPLACE_MODE_INTERSECT);
+ opVec.push_back(REPLACE_MODE_UNION);
+
+ ProgressData p;
+ vector<const FilterStreamData*> streamIn,streamOut;
+ streamIn.push_back(d);
+ for(unsigned int opId=0;opId<opVec.size();opId++)
+ {
+ s=TRANS(REPLACE_ALGORITHMS[opVec[opId]]);
+ TEST(f->setProperty(KEY_REPLACE_ALGORITHM,s,needUp),"Set prop");
+
+ //Do the refresh
+ TEST(!f->refresh(streamIn,streamOut,p),"refresh OK");
+
+ TEST(streamOut.size() == 1,"stream count");
+ TEST(streamOut[0]->getStreamType() == STREAM_TYPE_IONS,"stream type");
+ TEST(streamOut[0]->getNumBasicObjects() == NIONS,"Number objects");
+
+ //we should have taken the mass-to-charge from the file
+ const IonStreamData *outIons = (const IonStreamData*)streamOut[0];
+ for(unsigned int ui=0;ui<NIONS; ui++)
+ {
+ ASSERT(outIons->data[ui].getMassToCharge() == 1);
+ }
+ delete streamOut[0];
+ streamOut.clear();
+ }
+ delete f;
+ delete d;
+
+ wxRemoveFile(ionFile);
+
+
+ return true;
+}
+
+bool replaceSubtractTest()
+{
+ std::string ionFile=createTmpFilename(NULL,".pos");
+
+ vector<IonHit> ions;
+ const unsigned int NIONS=10;
+ const unsigned int DIFF_COUNT=5;
+ for(unsigned int ui=0;ui<NIONS;ui++)
+ {
+ IonHit h;
+ h = IonHit(Point3D(ui,ui,ui),1);
+
+ //make some ions different to the (x,x,x) pattern
+ if(ui < DIFF_COUNT)
+ {
+ h.setPos(h.getPos() - Point3D(0,0,100));
+ ions.push_back(h);
+ }
+ else
+ ions.push_back(h);
+ }
+
+ vector<IonHit> tmpI;
+ for(unsigned int ui=0;ui<NIONS;ui++)
+ {
+ if(ions[ui][2] < 0 )
+ {
+ tmpI.push_back(ions[ui]);
+ tmpI.back().setMassToCharge(2);
+ }
+ }
+
+ IonHit::makePos(tmpI,ionFile.c_str());
+ tmpI.clear();
+
+ IonStreamData *d = new IonStreamData;
+ d->data.swap(ions);
+
+ //Create a spatial analysis filter
+ SpatialAnalysisFilter *f=new SpatialAnalysisFilter;
+ f->setCaching(false);
+
+ //Set it to do a subtraction calculation
+ bool needUp;
+ string s;
+ s=TRANS(SPATIAL_ALGORITHMS[ALGORITHM_REPLACE]);
+ TEST(f->setProperty(KEY_ALGORITHM,s,needUp),"Set prop");
+ TEST(f->setProperty(KEY_REPLACE_FILE,ionFile,needUp),"Set prop");
+ s=TRANS(REPLACE_ALGORITHMS[REPLACE_MODE_SUBTRACT]);
+ TEST(f->setProperty(KEY_REPLACE_ALGORITHM,s,needUp),"Set prop");
+
+ //Do the refresh
+ ProgressData p;
+ vector<const FilterStreamData*> streamIn,streamOut;
+ streamIn.push_back(d);
+ TEST(!f->refresh(streamIn,streamOut,p),"refresh OK");
+ delete f;
+ delete d;
+ streamIn.clear();
+
+ TEST(streamOut.size() == 1,"stream count");
+ TEST(streamOut[0]->getStreamType() == STREAM_TYPE_IONS,"stream type");
+ TEST(streamOut[0]->getNumBasicObjects() == DIFF_COUNT,"Number objects");
+
+ //we should have taken the mass-to-charge from the original data,
+ // not the file
+ const IonStreamData *outIons = (const IonStreamData*)streamOut[0];
+ for(unsigned int ui=0;ui<outIons->getNumBasicObjects(); ui++)
+ {
+ ASSERT(outIons->data[ui].getMassToCharge() == 1);
+ ASSERT(outIons->data[ui].getPos()[2] >= 0);
+ }
+
+ wxRemoveFile(ionFile);
+
+ delete streamOut[0];
+
+ return true;
+}
+
+bool replaceUnionTest()
+{
+ std::string ionFile=createTmpFilename(NULL,".pos");
+
+ //"B" dataset
+ vector<IonHit> ions;
+ ions.push_back(IonHit(Point3D(0,0,0),1));
+ ions.push_back(IonHit(Point3D(1,0,1),1));
+ ions.push_back(IonHit(Point3D(0,1,1),1));
+
+ IonHit::makePos(ions,ionFile.c_str());
+ ions.clear();
+
+ //"A" dataset
+ ions.push_back(IonHit(Point3D(0,0,0),2));
+ ions.push_back(IonHit(Point3D(1,0,-1),2));
+ ions.push_back(IonHit(Point3D(0,1,-1),2));
+
+
+ IonStreamData *d = new IonStreamData;
+ d->data.swap(ions);
+
+ //Create a spatial analysis filter
+ SpatialAnalysisFilter *f=new SpatialAnalysisFilter;
+ f->setCaching(false);
//Set it to do a union calculation
bool needUp;
@@ -4644,13 +4878,11 @@
s=TRANS(SPATIAL_ALGORITHMS[ALGORITHM_REPLACE]);
TEST(f->setProperty(KEY_ALGORITHM,s,needUp),"Set prop");
TEST(f->setProperty(KEY_REPLACE_FILE,ionFile,needUp),"Set prop");
- s=TRANS(REPLACE_ALGORITHMS[REPLACE_MODE_INTERSECT]);
+ s=TRANS(REPLACE_ALGORITHMS[REPLACE_MODE_UNION]);
TEST(f->setProperty(KEY_REPLACE_ALGORITHM,s,needUp),"Set prop");
-
s="1";
TEST(f->setProperty(KEY_REPLACE_VALUE,s,needUp),"Set prop");
-
//Do the refresh
ProgressData p;
vector<const FilterStreamData*> streamIn,streamOut;
@@ -4662,14 +4894,16 @@
TEST(streamOut.size() == 1,"stream count");
TEST(streamOut[0]->getStreamType() == STREAM_TYPE_IONS,"stream type");
- TEST(streamOut[0]->getNumBasicObjects() == NIONS,"Number objects");
-
- //we should have taken the mass-to-charge from the file
+ TEST(streamOut[0]->getNumBasicObjects() == 5,"Number objects");
+
+ //There should be
const IonStreamData *outIons = (const IonStreamData*)streamOut[0];
- for(unsigned int ui=0;ui<NIONS; ui++)
+ float sumV=0;
+ for(unsigned int ui=0;ui<outIons->getNumBasicObjects(); ui++)
{
- ASSERT(outIons->data[ui].getMassToCharge() == 1);
+ sumV+=outIons->data[ui].getMassToCharge();
}
+ TEST( EQ_TOL(sumV,7.0f),"mass-to-charge check");
wxRemoveFile(ionFile);
@@ -4678,7 +4912,6 @@
return true;
}
-
//--- Local concentration tests --
const IonStreamData *createLCIonStream()
{
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/spectrumPlot.cpp
--- src/backend/filters/spectrumPlot.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/spectrumPlot.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -517,6 +517,8 @@
getOut.push_back(d);
+ progress.filterProgress=100;
+
return 0;
}
diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/transform.cpp
--- src/backend/filters/transform.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/filters/transform.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -998,8 +998,10 @@
break;
}
+ }
}
- }
+
+ progress.filterProgress=100;
}
else
{
@@ -1526,6 +1528,11 @@
case KEY_CROP_MINIMUM:
{
ASSERT(scalarParams.size() ==2);
+ float tmp;
+ if(stream_cast(tmp,value) || tmp >=scalarParams[1])
+ return false;
+
+
if(!applyPropertyNow(scalarParams[0],value,needUpdate))
return false;
break;
@@ -1533,6 +1540,9 @@
case KEY_CROP_MAXIMUM:
{
ASSERT(scalarParams.size() ==2);
+ float tmp;
+ if(stream_cast(tmp,value) || tmp <=scalarParams[0])
+ return false;
if(!applyPropertyNow(scalarParams[1],value,needUpdate))
return false;
break;
diff -r bcb9acfa66de -r effd078610a7 src/backend/plot.cpp
--- src/backend/plot.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/plot.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -29,7 +29,7 @@
NTRANS("Moving avg.")
};
-const char *plotTypeStrings[]= {
+const char *traceStyleStrings[]= {
NTRANS("Lines"),
NTRANS("Bars"),
NTRANS("Steps"),
@@ -119,15 +119,15 @@
string plotString(unsigned int plotMode)
{
ASSERT(plotMode< PLOT_TYPE_ENUM_END);
- return TRANS(plotTypeStrings[plotMode]);
+ return TRANS(traceStyleStrings[plotMode]);
}
unsigned int plotID(const std::string &plotString)
{
- COMPILE_ASSERT(THREEDEP_ARRAYSIZE(plotTypeStrings) == PLOT_TYPE_ENUM_END);
+ COMPILE_ASSERT(THREEDEP_ARRAYSIZE(traceStyleStrings) == PLOT_TYPE_ENUM_END);
for(unsigned int ui=0;ui<PLOT_TYPE_ENUM_END; ui++)
{
- if(plotString==TRANS(plotTypeStrings[ui]))
+ if(plotString==TRANS(traceStyleStrings[ui]))
return ui;
}
@@ -298,7 +298,7 @@
PlotWrapper::PlotWrapper()
{
- //COMPILE_ASSERT(THREEDEP_ARRAYSIZE(plotTypeStrings) == PLOT_TYPE_ENUM_END);
+ //COMPILE_ASSERT(THREEDEP_ARRAYSIZE(traceStyleStrings) == PLOT_TYPE_ENUM_END);
applyUserBounds=false;
plotChanged=true;
@@ -684,6 +684,12 @@
return visibleMode;
}
+unsigned int PlotWrapper::getPlotMode(unsigned int plotId) const
+{
+ ASSERT(plotId < plottingData.size());
+ return plottingData[plotId]->getPlotMode();
+}
+
void PlotWrapper::getVisibleIDs(vector<unsigned int> &visiblePlotIDs ) const
{
@@ -791,7 +797,7 @@
if(!plottingData[ui]->visible)
continue;
- if(plottingData[ui]->getType()!= PLOT_MODE_1D)
+ if(plottingData[ui]->getMode()!= PLOT_MODE_1D)
continue;
if(((Plot1D*)plottingData[ui])->wantLogPlot())
@@ -809,7 +815,7 @@
float minYVal=0.1;
for(size_t ui=0;ui<plottingData.size();ui++)
{
- if(!plottingData[ui]->visible || plottingData[ui]->getType() !=PLOT_MODE_1D)
+ if(!plottingData[ui]->visible || plottingData[ui]->getMode() !=PLOT_MODE_1D)
continue;
float tmp ;
@@ -929,7 +935,7 @@
Plot2DFunc *curPlot;
curPlot=(Plot2DFunc*)plottingData[ui];
- if(curPlot->getType() == PLOT_2D_DENS)
+ if(curPlot->getMode() == PLOT_2D_DENS)
{
wantColourbar=true;
}
@@ -1047,11 +1053,6 @@
plottingData[plotIDHandler.getPos(plotId)]->regionGroup.getRegion(regionId,region);
}
-unsigned int PlotWrapper::plotType(unsigned int plotId) const
-{
- return plottingData[plotIDHandler.getPos(plotId)]->getPlotMode();
-}
-
void PlotWrapper::moveRegion(unsigned int plotID, unsigned int regionId, bool regionSelfUpdate,
unsigned int movementType, float newX, float newY) const
@@ -1135,7 +1136,7 @@
void PlotBase::copyBase(PlotBase *target) const
{
- target->plotType=plotType;
+ target->traceStyle=traceStyle;
target->minX=minX;
target->maxX=maxX;
target->minY=minY;
@@ -1157,12 +1158,12 @@
unsigned int PlotBase::getType() const
{
- return plotType;
+ return traceStyle;
}
unsigned int PlotBase::getMode() const
{
- switch(plotType)
+ switch(traceStyle)
{
case PLOT_LINE_LINES:
case PLOT_LINE_BARS:
@@ -1181,7 +1182,7 @@
Plot1D::Plot1D()
{
//Set the default plot properties
- plotType=PLOT_LINE_LINES;
+ traceStyle=PLOT_LINE_LINES;
plotMode=PLOT_MODE_1D;
xLabel="";
yLabel="";
@@ -1489,7 +1490,7 @@
//Plot the appropriate form
- switch(plotMode)
+ switch(traceStyle)
{
case PLOT_LINE_LINES:
//Unfortunately, when using line plots, mathgl moves the data points to the plot boundary,
@@ -1632,7 +1633,7 @@
Plot2DFunc::Plot2DFunc()
{
plotMode = PLOT_MODE_2D;
- plotType=PLOT_2D_DENS;
+ traceStyle=PLOT_2D_DENS;
}
void Plot2DFunc::setData(const Array2D<float> &a,
@@ -1705,7 +1706,8 @@
Plot2DScatter::Plot2DScatter()
{
- plotType=PLOT_2D_SCATTER;
+ plotMode=PLOT_2D_SCATTER;
+ traceStyle=PLOT_LINE_POINTS;
scatterIntensityLog=false;
}
diff -r bcb9acfa66de -r effd078610a7 src/backend/plot.h
--- src/backend/plot.h Tue May 31 13:04:58 2016 +1000
+++ src/backend/plot.h Tue Jun 21 12:45:20 2016 +0100
@@ -217,7 +217,7 @@
class PlotBase
{
protected:
- //!Sub type of plot (eg lines, bars for 1D)
+ //!Type of plot
unsigned int plotMode;
//!xaxis label
std::string xLabel;
@@ -229,8 +229,9 @@
//plot colour (for single coloured plots)
float r,g,b;
- //The type of plot (ie what class is it?)
- unsigned int plotType;
+ //The sub-style of the plot trace (eg lines, points, bars, etc)
+ // FIXME: This is badly named, change to traceStyle, or dataStyle, or something
+ unsigned int traceStyle;
void copyBase(PlotBase *target) const;
@@ -297,8 +298,12 @@
void setStrings(const std::string &x,
const std::string &y,const std::string &t);
+ //Set the colour of the plot trace
void setColour(float rNew, float gNew, float bNew);
+ //set the visual style for the trace (dots, lines, etc)
+ void setTraceStyle(unsigned int newStyle) { traceStyle=newStyle;}
+
std::string getXLabel() const { return xLabel;}
std::string getTitle() const { return title;}
std::string getYLabel() const { return yLabel;}
@@ -309,6 +314,7 @@
void setPlotMode(unsigned int newMode) { plotMode= newMode;}
+ //get the colour of the trace
void getColour(float &r, float &g, float &b) const ;
#ifdef DEBUG
@@ -613,7 +619,7 @@
//!obtain the type of a plot, given the plot's uniqueID
- unsigned int plotType(unsigned int plotId) const;
+ unsigned int getPlotMode(unsigned int plotId) const;
//Retrieve the types of visible plots
unsigned int getVisibleMode() const;
diff -r bcb9acfa66de -r effd078610a7 src/backend/viscontrol.cpp
--- src/backend/viscontrol.cpp Tue May 31 13:04:58 2016 +1000
+++ src/backend/viscontrol.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -249,7 +249,7 @@
plotData->yLabel,plotData->dataLabel);
//set the appearance of the plot
- //plotNew->setTraceStyle(plotStyle);
+ plotNew->setTraceStyle(plotData->plotStyle);
plotNew->setColour(plotData->r,plotData->g,plotData->b);
@@ -275,7 +275,7 @@
unsigned int plotID;
PlotBase *plotNew;
- switch(plotData->plotType)
+ switch(plotData->plotStyle)
{
case PLOT_2D_DENS:
{
diff -r bcb9acfa66de -r effd078610a7 src/common/basics.cpp
--- src/common/basics.cpp Tue May 31 13:04:58 2016 +1000
+++ src/common/basics.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -1347,7 +1347,8 @@
while(CFile.good() && !CFile.eof() && atHeader)
{
//Grab a line from the file
- CFile.getline(inBuffer,BUFFER_SIZE);
+ if(!CFile.getline(inBuffer,BUFFER_SIZE))
+ break;
if(!CFile.good())
return ERR_FILE_FORMAT;
@@ -1457,10 +1458,8 @@
}
//Grab a line from the file
- CFile.getline(inBuffer,BUFFER_SIZE);
-
- if(!CFile.good() && !CFile.eof())
- return ERR_FILE_FORMAT;
+ if(!CFile.getline(inBuffer,BUFFER_SIZE))
+ break;
}
return 0;
diff -r bcb9acfa66de -r effd078610a7 src/gui/mainFrame.cpp
--- src/gui/mainFrame.cpp Tue May 31 13:04:58 2016 +1000
+++ src/gui/mainFrame.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -1391,7 +1391,7 @@
updateWxTreeCtrl(treeFilters);
if(!noUpdate)
- return doSceneUpdate(true);
+ doSceneUpdate(true);
return true;
}
@@ -3834,7 +3834,7 @@
}
-bool MainWindowFrame::doSceneUpdate(bool ensureVisible)
+void MainWindowFrame::doSceneUpdate(bool ensureVisible)
{
//Update scene
ASSERT(!currentlyUpdatingScene);
@@ -3864,6 +3864,11 @@
ensureResultVisible=ensureVisible;
ASSERT(!refreshControl);
+
+ //Hack to prevent crash on double-refresh
+ if(refreshControl)
+ return;
+
refreshControl = new RefreshController(visControl.state.treeState);
refreshThread=new RefreshThread(this,refreshControl);
progressTimer->Start(PROGRESS_TIMER_DELAY);
@@ -3871,7 +3876,8 @@
refreshThread->Create();
refreshThread->Run();
- return true;
+ cerr << "Updating scene complete"<< endl;
+ return;
}
void MainWindowFrame::updateWxTreeCtrl( wxTreeCtrl *t, const Filter *f)
@@ -3971,6 +3977,11 @@
ASSERT(!visControl.state.treeState.isRefreshing());
progressTimer->Stop();
+ //Hack to prevent crash on re-entry during refresh. Should never trigger.
+ if(!refreshControl)
+ return;
+
+
vector<std::pair<const Filter*, std::string> > consoleMessages;
consoleMessages=refreshControl->getConsoleMessages();
diff -r bcb9acfa66de -r effd078610a7 src/gui/mainFrame.h
--- src/gui/mainFrame.h Tue May 31 13:04:58 2016 +1000
+++ src/gui/mainFrame.h Tue Jun 21 12:45:20 2016 +0100
@@ -124,7 +124,7 @@
//!Update the progress information in the status bar
void updateProgressStatus();
//!Perform an update to the 3D Scene. Returns false if refresh failed
- bool doSceneUpdate(bool ensureResultVisible=false);
+ void doSceneUpdate(bool ensureResultVisible=false);
//!Complete the scene update. Returns false if failed
void finishSceneUpdate(unsigned int errCode);
diff -r bcb9acfa66de -r effd078610a7 src/gui/mathglPane.cpp
--- src/gui/mathglPane.cpp Tue May 31 13:04:58 2016 +1000
+++ src/gui/mathglPane.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -627,7 +627,7 @@
thePlot->getRegion(plotId,regionId,r);
//TODO: Implement a more generic region handler?
- ASSERT(thePlot->plotType(plotId) == PLOT_MODE_1D);
+ ASSERT(thePlot->getPlotMode(plotId) == PLOT_MODE_1D);
float mglStartX,mglStartY;
toPlotCoords(draggingStart.x, draggingStart.y,mglStartX,mglStartY);
@@ -1471,7 +1471,7 @@
return;
- ASSERT(thePlot->plotType(startMousePlot) == PLOT_MODE_1D);
+ ASSERT(thePlot->getPlotMode(startMousePlot) == PLOT_MODE_1D);
//See where extending the region is allowed up to.
thePlot->findRegionLimit(startMousePlot,startMouseRegion,
@@ -1550,7 +1550,7 @@
{
//This needs to be extended to support more
//plot types.
- ASSERT(thePlot->plotType(startMousePlot) == PLOT_MODE_1D);
+ ASSERT(thePlot->getPlotMode(startMousePlot) == PLOT_MODE_1D);
//Draw "ghost" limits markers for move,
//these appear as moving vertical bars to outline
diff -r bcb9acfa66de -r effd078610a7 src/wx/wxcomponents.cpp
--- src/wx/wxcomponents.cpp Tue May 31 13:04:58 2016 +1000
+++ src/wx/wxcomponents.cpp Tue Jun 21 12:45:20 2016 +0100
@@ -188,14 +188,14 @@
void CopyGrid::saveData()
{
- wxFileDialog *wxF = new wxFileDialog(this,TRANS("Save Data..."), wxT(""),
+ wxFileDialog wxF(this,TRANS("Save Data..."), wxT(""),
wxT(""),TRANS("Text File (*.txt)|*.txt|All Files (*)|*"),wxFD_SAVE);
- if( (wxF->ShowModal() == wxID_CANCEL))
+ if( (wxF.ShowModal() == wxID_CANCEL))
return;
- std::string dataFile = stlStr(wxF->GetPath());
+ std::string dataFile = stlStr(wxF.GetPath());
ofstream f(dataFile.c_str());
if(!f)