1 #include "BinningLayer.hpp" 5 BinningLayer::BinningLayer(
const char *name, HyPerCol *hc) {
10 BinningLayer::BinningLayer() {
15 int BinningLayer::initialize_base() {
20 int BinningLayer::initialize(
const char *name, HyPerCol *hc) {
38 parent->parameters()->ioParamStringRequired(
39 ioFlag, name,
"originalLayerName", &mOriginalLayerName);
40 assert(mOriginalLayerName);
41 if (ioFlag == PARAMS_IO_READ && mOriginalLayerName[0] ==
'\0') {
42 if (parent->columnId() == 0) {
43 ErrorLog().printf(
"%s: originalLayerName must be set.\n", getDescription_c());
45 MPI_Barrier(parent->getCommunicator()->communicator());
51 parent->parameters()->ioParamValue(ioFlag, name,
"binMin", &mBinMin, mBinMin);
55 pvAssert(!parent->parameters()->presentAndNotBeenRead(name,
"binMin"));
56 parent->parameters()->ioParamValue(ioFlag, name,
"binMax", &mBinMax, mBinMax);
57 if (ioFlag == PARAMS_IO_READ && mBinMax <= mBinMin) {
58 if (parent->columnId() == 0) {
60 "%s: binMax (%f) must be greater than binMin (%f).\n",
65 MPI_Barrier(parent->getCommunicator()->communicator());
71 parent->parameters()->ioParamValue(ioFlag, name,
"binSigma", &mBinSigma, mBinSigma);
75 parent->parameters()->ioParamValue(ioFlag, name,
"delay", &mDelay, mDelay);
79 parent->parameters()->ioParamValue(ioFlag, name,
"zeroNeg", &mZeroNeg, mZeroNeg);
83 parent->parameters()->ioParamValue(ioFlag, name,
"zeroDCR", &mZeroDCR, mZeroDCR);
89 BinningLayer::communicateInitInfo(std::shared_ptr<CommunicateInitInfoMessage const> message) {
90 auto status = HyPerLayer::communicateInitInfo(message);
94 mOriginalLayer = message->lookup<
HyPerLayer>(std::string(mOriginalLayerName));
95 if (mOriginalLayer == NULL) {
96 if (parent->columnId() == 0) {
98 "%s: originalLayerName \"%s\" is not a layer in the HyPerCol.\n",
102 MPI_Barrier(parent->getCommunicator()->communicator());
106 return Response::POSTPONE;
108 mOriginalLayer->synchronizeMarginWidth(
this);
109 this->synchronizeMarginWidth(mOriginalLayer);
110 const PVLayerLoc *srcLoc = mOriginalLayer->getLayerLoc();
112 assert(srcLoc != NULL && loc != NULL);
113 if (srcLoc->nxGlobal != loc->nxGlobal || srcLoc->nyGlobal != loc->nyGlobal) {
114 if (parent->columnId() == 0) {
115 ErrorLog(errorMessage);
117 "%s: originalLayerName \"%s\" does not have the same dimensions.\n",
121 " original (nx=%d, ny=%d) versus (nx=%d, ny=%d)\n",
127 MPI_Barrier(parent->getCommunicator()->communicator());
130 if (srcLoc->nf != 1) {
132 "%s: originalLayerName \"%s\" can only have 1 feature.\n",
136 assert(srcLoc->nx == loc->nx && srcLoc->ny == loc->ny);
137 return Response::SUCCESS;
140 Response::Status BinningLayer::allocateDataStructures() {
141 return HyPerLayer::allocateDataStructures();
144 void BinningLayer::allocateV() {
149 void BinningLayer::initializeV() { assert(getV() == NULL); }
151 void BinningLayer::initializeActivity() {}
153 Response::Status BinningLayer::updateState(
double simTime,
double dt) {
154 PVLayerLoc const *origLoc = mOriginalLayer->getLayerLoc();
157 pvAssert(origLoc->nx == currLoc->nx);
158 pvAssert(origLoc->ny == currLoc->ny);
159 pvAssert(origLoc->nf == 1);
160 int nx = currLoc->nx;
161 int ny = currLoc->ny;
163 pvAssert(origLoc->halo.lt == currLoc->halo.lt);
164 pvAssert(origLoc->halo.rt == currLoc->halo.rt);
165 pvAssert(origLoc->halo.dn == currLoc->halo.dn);
166 pvAssert(origLoc->halo.up == currLoc->halo.up);
167 PVHalo const *halo = &origLoc->halo;
169 int numBins = currLoc->nf;
170 float binRange = mBinMax - mBinMin;
171 float stepSize = float(binRange) / numBins;
173 int const nxExt = origLoc->nx + origLoc->halo.lt + origLoc->halo.rt;
174 int const nyExt = origLoc->ny + origLoc->halo.dn + origLoc->halo.up;
176 float const *origData = mOriginalLayer->
getLayerData(mDelay);
177 float *currActivity = getActivity();
179 int nbatch = currLoc->nbatch;
180 pvAssert(origLoc->nbatch == currLoc->nbatch);
181 for (
int b = 0; b < nbatch; b++) {
182 const float *origDataBatch = origData + b * nxExt * nyExt * origLoc->nf;
183 float *currABatch = currActivity + b * nxExt * nyExt * currLoc->nf;
185 #ifdef PV_USE_OPENMP_THREADS 186 #pragma omp parallel for 188 for (
int kExt = 0; kExt < nxExt * nyExt * currLoc->nf; kExt++) {
189 int iX = kxPos(kExt, nxExt, nyExt, currLoc->nf);
190 int iY = kyPos(kExt, nxExt, nyExt, currLoc->nf);
191 int iF = featureIndex(kExt, nxExt, nyExt, currLoc->nf);
193 int origIndex = kIndex(iX, iY, 0, nxExt, nyExt, 1);
194 float inVal = origDataBatch[origIndex];
197 inVal = inVal < mBinMin ? mBinMin : inVal > mBinMax ? mBinMax : inVal;
199 int const outOfBinValue = mZeroNeg ? 0 : -1;
200 if (mZeroDCR && inVal == 0) {
201 currABatch[kExt] = outOfBinValue;
205 if (mBinSigma == 0) {
206 int featureIdx = std::floor((inVal - mBinMin) / stepSize);
207 if (featureIdx >= numBins) {
208 featureIdx = numBins - 1;
210 currABatch[kExt] = iF == featureIdx ? 1 : outOfBinValue;
215 float binCenter = ((float)iF + 0.5f) * stepSize;
216 currABatch[kExt] = calcGaussian(inVal - binCenter, mBinSigma * stepSize);
221 return Response::SUCCESS;
224 float BinningLayer::calcGaussian(
float x,
float sigma) {
225 return std::exp(-x * x / (2 * sigma * sigma));
228 BinningLayer::~BinningLayer() {
229 free(mOriginalLayerName);
void ioParam_zeroDCR(enum ParamsIOFlag ioFlag)
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
void ioParam_originalLayerName(enum ParamsIOFlag ioFlag)
void ioParam_binSigma(enum ParamsIOFlag ioFlag)
void ioParam_binMax(enum ParamsIOFlag ioFlag)
void ioParam_delay(enum ParamsIOFlag ioFlag)
int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
static bool completed(Status &a)
void ioParam_zeroNeg(enum ParamsIOFlag ioFlag)
int initialize(const char *name, HyPerCol *hc)
void ioParam_binMin(enum ParamsIOFlag ioFlag)
const float * getLayerData(int delay=0)
bool getInitInfoCommunicatedFlag() const