diff -r bcb9acfa66de -r effd078610a7 .hgtags --- a/.hgtags Tue May 31 13:04:58 2016 +1000 +++ b/.hgtags Tue Jun 21 12:45:20 2016 +0100 @@ -16,3 +16,4 @@ 9fcee7d53bc2a2b69db9dbe59c6f1264615a54e4 3Depict-0.0.16 19a65d51c5d65ebf3d8b7760cfa4edde36c251c0 3Depict-0.0.17 910618ab1f369c5a9253965e12f5d8f75fceb0c6 3Depict-0.0.18 +bcb9acfa66de56f6531016d1e81a68d7118b7b35 3Depict-0.0.19 diff -r bcb9acfa66de -r effd078610a7 docs/manual-latex/build-latex.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 --- a/src/backend/filter.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/filter.h Tue May 31 13:04:58 2016 +1000 +++ b/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 xyData; diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/algorithms/rdf.cpp --- a/src/backend/filters/algorithms/rdf.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/filters/annotation.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/filters/boundingBox.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/filters/clusterAnalysis.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/filters/ionColour.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/filters/ionDownsample.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/filters/ionInfo.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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::epsilon())) @@ -420,6 +420,9 @@ } } + + progress.filterProgress=100; + return 0; } diff -r bcb9acfa66de -r effd078610a7 src/backend/filters/spatialAnalysis.cpp --- a/src/backend/filters/spatialAnalysis.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 nearestVec; - nearestVec.resize(inIons.size()); - - //TODO: pair vector might be faster - // as we can use it in sequence, and can use openmp - map matchedMap; - - //Find the nearest point for all points in the dataset - - #pragma omp parallel for - for(size_t ui=0;ui 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 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 nearestVec; + nearestVec.resize(inIons.size()); + + //TODO: pair vector might be faster + // as we can use it in sequence, and can use openmp + map 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 matchedMap.size()) - outIons.reserve(inIons.size()-matchedMap.size()); - - // - #pragma omp parallel for - for(unsigned int ui=0;ui::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::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::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::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::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::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::const_iterator it=matchedMap.begin(); + + + for(unsigned int ui=0;uifirst == 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;ujdata.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::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 opVec; + opVec.push_back(REPLACE_MODE_INTERSECT); + opVec.push_back(REPLACE_MODE_UNION); + + ProgressData p; + vector streamIn,streamOut; + streamIn.push_back(d); + for(unsigned int opId=0;opIdsetProperty(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;uidata[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 ions; + const unsigned int NIONS=10; + const unsigned int DIFF_COUNT=5; + for(unsigned int ui=0;ui tmpI; + for(unsigned int ui=0;uidata.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 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;uigetNumBasicObjects(); 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 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 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;uigetNumBasicObjects(); 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 --- a/src/backend/filters/spectrumPlot.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/filters/transform.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/plot.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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;uigetPlotMode(); +} + void PlotWrapper::getVisibleIDs(vector &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;uivisible || 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 &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 --- a/src/backend/plot.h Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/backend/viscontrol.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/common/basics.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/gui/mainFrame.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 > consoleMessages; consoleMessages=refreshControl->getConsoleMessages(); diff -r bcb9acfa66de -r effd078610a7 src/gui/mainFrame.h --- a/src/gui/mainFrame.h Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/gui/mathglPane.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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 --- a/src/wx/wxcomponents.cpp Tue May 31 13:04:58 2016 +1000 +++ b/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)