Variant ReflectedGroupItem::getData( int column, size_t roleId ) const { auto obj = getRootObject(); if (obj == nullptr) { return Variant(); } auto definition = getDefinition(); if (definition == nullptr) { return Variant(); } if (roleId == IndexPathRole::roleId_) { if (parent_ == nullptr) { return displayName_; } std::string parentIndexPath = parent_->getPath(); return parentIndexPath + displayName_; } else if (roleId == ObjectRole::roleId_) { return getObject();; } else if (roleId == RootObjectRole::roleId_) { return getRootObject(); } if (roleId == ValueRole::roleId_) { auto collectionHolder = std::make_shared< CollectionHolder< Variants > >(); Variants& childValues_ = collectionHolder->storage(); getChildValues(childValues_); return std::move( Collection( collectionHolder ) ); } return Variant(); }
// ###################################################################### void SimulationViewerStats::save1(const ModelComponentSaveInfo& sinfo) { // Use a LINFO here since we are already slowed down by writing // stats, we should at least have a short debug on this fact LINFO("SAVING STATS TO %s",itsStatsFname.getVal().c_str()); // Lock the file. We put this here to support multi-process in the // future. However, this will not work on NFS mounts. struct flock fl; int fd; lockFile(itsStatsFname.getVal().c_str(),fd,fl); // Since this is more or less debug info we open and flush every iteration. // rather than once each run. std::ofstream statsFile; statsFile.open(itsStatsFname.getVal().c_str(),std::ios_base::app); // get the OFS to save to, assuming sinfo is of type // SimModuleSaveInfo (will throw a fatal exception otherwise): nub::ref<FrameOstream> ofs = dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs; // also get the SimEventQueue: SimEventQueue *q = dynamic_cast<const SimModuleSaveInfo&>(sinfo).q; // initialize our stats dump file if desired: if(itsFrameIdx == 0) { rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this)); q->request(vcxm); // VisualCortex is now filling-in the maps... if (itsStatsFname.getVal().size()) { itsStatsFile = new std::ofstream(itsStatsFname.getVal().c_str()); if (itsStatsFile->is_open() == false) LFATAL("Failed to open '%s' for writing.", itsStatsFname.getVal().c_str()); // dump the settings of the model: getRootObject()->printout(*itsStatsFile, "# "); // list all our channels: //LFATAL("FIXME"); // also get the SimEventQueue: rutz::shared_ptr<ChannelMaps> chm = vcxm->channelmaps(); uint numSubmaps = chm->numSubmaps(); *itsStatsFile << "# CHANNELS: "; for(uint i = 0; i < numSubmaps; i++) { NamedImage<float> smap = chm->getRawCSmap(i); *itsStatsFile << smap.name() << ", "; } *itsStatsFile << std::endl; } } // We flush frequently since this output is debuggy in nature or it's being used // to collect information which needs assurance of accuracy for instance in // RSVP analysis. It is better to err on the side of caution. (*itsStatsFile).flush(); (*itsStatsFile).close(); // get the basic input frame info if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this)) { itsSizeX = e->frame().getWidth(); itsSizeY = e->frame().getHeight(); itsFrameNumber = (unsigned int)e->frameNum(); itsFrameIdx = itsFrameNumber; } else { itsFrameNumber = itsFrameIdx; itsFrameIdx++; } // get the latest input frame: // Since we are only using it's basic statistics (Height / Width) , we don't care about it's // blackboard status. Use SEQ_ANY then. Otherwise, this will not fetch at any rate. Image< PixRGB<byte> > input; if (SeC<SimEventRetinaImage> e = q->check<SimEventRetinaImage>(this,SEQ_ANY)) input = e->frame().colorByte(); else LINFO("No input? Check the SimEventCue."); // Get the current frame number or keep track on your own /* if (SeC<SimEventInputFrame> e = q->check<SimEventInputFrame>(this)) itsFrameIdx = e->frameNum(); else itsFrameIdx++; */ // get the latest raw AGM: Image<float> agm; if (SeC<SimEventAttentionGuidanceMapOutput> e = q->check<SimEventAttentionGuidanceMapOutput>(this)) agm = e->agm(1.0F); else LINFO("No AGM? Check the SimEventCue."); // if we are missing input or agm, return: // We also need to warn so that we know why the stats file may be empty bool quit = false; if (input.initialized() == false) { LINFO("WARNING!!! Input seems not to be initialized, so detailed stats cannot be saved."); quit = true; } if(agm.initialized() == false) { LINFO("WARNING!!! NO Attention Guidance MAP \"AGM\" so detailed stats cannot be saved."); quit = true; } if(quit == true) return; // update the trajectory: Image< PixRGB<byte> > res; const int w = input.getWidth(); // save image results? if so let's prepare it if (itsSaveXcombo.getVal() || itsSaveYcombo.getVal()) { Image<float> nagm = getMap(*q); res = colGreyCombo(input, nagm, itsSaveXcombo.getVal(), itsDisplayInterp.getVal()); } // if we are saving single channel stats save saliency stats using a compatable format // SEE: SingleChannel.C / saveStats(..) for more info on format if (itsGetSingleChannelStats.getVal()) saveCompat(agm); // Save a bunch of stats? if (statsFile) { // start with the current simulation time: statsFile <<std::endl<<"= "<<q->now().msecs() <<" # time of frame in ms"<<std::endl; // get min/max/avg and stdev and number of peaks in AGM: float mi, ma, av; getMinMaxAvg(agm, mi, ma, av); double sdev = stdev(agm); double peaksum; int npeaks = findPeaks(agm, 0.0f, 255.0f, peaksum); // find the location of max in the AGM, at scale of original input: float maxval; Point2D<int> maxloc; findMax(agm, maxloc, maxval); float scale = float(w) / float(agm.getWidth()); maxloc.i = int(maxloc.i * scale + 0.4999F); maxloc.j = int(maxloc.j * scale + 0.4999F); if (res.initialized()) { drawPatch(res, maxloc, 4, COL_YELLOW); drawPatch(res, maxloc + Point2D<int>(w, 0), 4, COL_YELLOW); } // find the location of min in the AGM, at scale of original input: float minval; Point2D<int> minloc; findMin(agm, minloc, minval); minloc.i = int(minloc.i * scale + 0.4999F); minloc.j = int(minloc.j * scale + 0.4999F); if (res.initialized()) { drawPatch(res, minloc, 4, COL_GREEN); drawPatch(res, minloc + Point2D<int>(w, 0), 4, COL_GREEN); } // save some stats for that location: statsFile <<maxloc.i<<' '<<maxloc.j<<' '<<minloc.i<<' ' <<minloc.j<<' '<<ma<<' '<<mi<<' '<<av<<' '<<sdev <<' '<<npeaks<<' '<<peaksum <<" # Xmax Ymax Xmin Ymin max min avg std npeaks peaksum" <<std::endl; // build a vector of points where we will save samples. First is // the max, second the min, then a bunch of random locations: std::vector<Point2D<int> > loc; loc.push_back(maxloc); loc.push_back(minloc); for (uint n = 0; n < 100; n ++) loc.push_back(Point2D<int>(randomUpToNotIncluding(input.getWidth()), randomUpToNotIncluding(input.getHeight()))); // Get all the conspicuity maps: ImageSet<float> cmap; //LFATAL("FIXME"); rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this)); q->request(vcxm); // VisualCortex is now filling-in the maps... rutz::shared_ptr<ChannelMaps> chm = vcxm->channelmaps(); uint numSubmaps = chm->numSubmaps(); for(uint i=0;i < numSubmaps; i++) { NamedImage<float> tempMap = chm->getRawCSmap(i); Image<float> m = tempMap; cmap.push_back(m); // also store sample points at the min/max locations: Point2D<int> p; float v; findMax(m, p, v); loc.push_back(p); findMin(m, p, v); loc.push_back(p); } /* for (uint i = 0; i < itsBrain->getVC()->numChans(); i ++) { Image<float> m = itsBrain->getVC()->subChan(i)->getOutput(); cmap.push_back(m); // also store sample points at the min/max locations: Point2D<int> p; float v; findMax(m, p, v); loc.push_back(p); findMin(m, p, v); loc.push_back(p); } */ // Go over all sample points and save feature map and // conspicuity map values at those locations: for (uint i = 0; i < loc.size(); i ++) { Point2D<int> p = loc[i]; Point2D<int> pp(int(p.i / scale), int(p.j / scale)); statsFile <<p.i<<' '<<p.j<<" "; // do the conspicuity maps first. Since they are all at the // scale of the AGM, we use pp: for (uint j = 0; j < cmap.size(); j ++) { if((int(p.i / scale) < agm.getWidth()) && (int(p.j / scale) < agm.getHeight())) { (statsFile)<<cmap[j].getVal(pp)<<' '; (statsFile)<<" "; } else { (statsFile)<<"-1"<<' '; (statsFile)<<" "; } } // now the feature maps, we use coordinates p: /* TOO BOGUS - disabled for now std::vector<double> f; itsBrain->getVC()->getFeatures(p, f); for (uint j = 0; j < f.size(); j ++) (*statsFile)<<f[j]<<' '; */ statsFile <<"# features "<<i<<" at ("<<p.i <<", "<<p.j<<')'<<std::endl; } } statsFile.flush(); statsFile.close(); unlockFile(itsStatsFname.getVal().c_str(),fd,fl); // save results? if (res.initialized()) ofs->writeRGB(res, "T", FrameInfo("SimulationViewerStats trajectory", SRC_POS)); // Should we compute attention gate stats // If we have AG stats we will save the basic LAM stats anyways if(itsComputeAGStats.getVal()) computeAGStats(*q); else if (SeC<SimEventAttentionGateOutput> ag = q->check<SimEventAttentionGateOutput>(this)) computeLAMStats(ag->lam()); //! Save the overlap image if(itsOverlap.initialized()) ofs->writeRGB(itsOverlap, "AG-STAT-MASK", FrameInfo("Stats mask overlap", SRC_POS)); if(itsVisualSegments.initialized()) ofs->writeRGB(itsVisualSegments, "AG-STAT-SEGS", FrameInfo("Stats segments", SRC_POS)); if(itsVisualCandidates.initialized()) ofs->writeGray(itsVisualCandidates, "AG-STAT-CAND", FrameInfo("Stats candidates", SRC_POS)); }
SFC::Project getRoot( void ) { return SFC::Project::Cast( getRootObject() ); }