#include "areatime.h"
#include "recapture.h"
#include "fleet.h"
#include "stock.h"
#include "stockprey.h"
#include "errorhandler.h"
#include "mathfunc.h"
#include "readfunc.h"
#include "readword.h"
#include "readaggregation.h"
#include "gadget.h"
#include "global.h"
Recaptures::Recaptures(CommentStream& infile, const AreaClass* const Area,
const TimeClass* const TimeInfo, double weight, TagPtrVector Tag, const char* name)
: Likelihood(TAGLIKELIHOOD, weight, name), alptr(0) {
aggregator = 0;
char text[MaxStrLength];
strncpy(text, "", MaxStrLength);
int i, j, check;
int numarea = 0, numlen = 0;
char datafilename[MaxStrLength];
char aggfilename[MaxStrLength];
strncpy(datafilename, "", MaxStrLength);
strncpy(aggfilename, "", MaxStrLength);
ifstream datafile;
CommentStream subdata(datafile);
functionname = new char[MaxStrLength];
strncpy(functionname, "", MaxStrLength);
readWordAndValue(infile, "datafile", datafilename);
readWordAndValue(infile, "function", functionname);
if (strcasecmp(functionname, "poisson") == 0)
functionnumber = 1;
else
handle.logFileMessage(LOGFAIL, "\nError in recaptures - unrecognised function", functionname);
//read in area aggregation from file
readWordAndValue(infile, "areaaggfile", aggfilename);
datafile.open(aggfilename, ios::in);
handle.checkIfFailure(datafile, aggfilename);
handle.Open(aggfilename);
numarea = readAggregation(subdata, areas, areaindex);
handle.Close();
datafile.close();
datafile.clear();
//Must change from outer areas to inner areas.
for (i = 0; i < areas.Nrow(); i++)
for (j = 0; j < areas.Ncol(i); j++)
areas[i][j] = Area->getInnerArea(areas[i][j]);
//read in length aggregation from file
readWordAndValue(infile, "lenaggfile", aggfilename);
datafile.open(aggfilename, ios::in);
handle.checkIfFailure(datafile, aggfilename);
handle.Open(aggfilename);
numlen = readLengthAggregation(subdata, lengths, lenindex);
handle.Close();
datafile.close();
datafile.clear();
//read in the fleetnames
i = 0;
infile >> text >> ws;
if (strcasecmp(text, "fleetnames") != 0)
handle.logFileUnexpected(LOGFAIL, "fleetnames", text);
infile >> text;
while (!infile.eof() && (strcasecmp(text, "[component]") != 0)) {
fleetnames.resize(new char[strlen(text) + 1]);
strcpy(fleetnames[i++], text);
infile >> text >> ws;
}
if (fleetnames.Size() == 0)
handle.logFileMessage(LOGFAIL, "\nError in recaptures - failed to read fleets");
handle.logMessage(LOGMESSAGE, "Read fleet data - number of fleets", fleetnames.Size());
//We have now read in all the data from the main likelihood file
//But we have to read in the recapture data from datafilename
datafile.open(datafilename, ios::in);
handle.checkIfFailure(datafile, datafilename);
handle.Open(datafilename);
readRecaptureData(subdata, TimeInfo, numarea, numlen);
handle.Close();
datafile.close();
datafile.clear();
for (j = 0; j < tagnames.Size(); j++) {
check = 0;
for (i = 0; i < Tag.Size(); i++) {
if (strcasecmp(tagnames[j], Tag[i]->getName()) == 0) {
check++;
tagvec.resize(Tag[i]);
//likelihoodValues.AddRows(1, Tag[i]->getNumTagTimeSteps(), 0.0);
}
}
if (check == 0)
handle.logMessage(LOGFAIL, "Error in recaptures - failed to match tag", tagnames[j]);
}
}
void Recaptures::readRecaptureData(CommentStream& infile,
const TimeClass* const TimeInfo, int numarea, int numlen) {
int i, j, k;
double tmpnumber;
char tmparea[MaxStrLength], tmplength[MaxStrLength], tmptagid[MaxStrLength];
strncpy(tmparea, "", MaxStrLength);
strncpy(tmplength, "", MaxStrLength);
strncpy(tmptagid, "", MaxStrLength);
int keepdata, timeid, areaid, lenid, tid;
int year, step, count, reject;
char* tagName;
infile >> ws;
//Check the number of columns in the inputfile
if (countColumns(infile) != 6)
handle.logFileMessage(LOGFAIL, "wrong number of columns in inputfile - should be 6");
year = step = count = reject = 0;
while (!infile.eof()) {
keepdata = 1;
infile >> tmptagid >> year >> step >> tmparea >> tmplength >> tmpnumber >> ws;
//crude check to see if something has gone wrong and avoid infinite loops
if (strlen(tmparea) == 0)
handle.logFileMessage(LOGFAIL, "failed to read data from file");
//if tmparea is in areaindex find areaid, else dont keep the data
areaid = -1;
for (i = 0; i < areaindex.Size(); i++)
if (strcasecmp(areaindex[i], tmparea) == 0)
areaid = i;
if (areaid == -1)
keepdata = 0;
//if tmplength is in lenindex find lenid, else dont keep the data
lenid = -1;
for (i = 0; i < lenindex.Size(); i++)
if (strcasecmp(lenindex[i], tmplength) == 0)
lenid = i;
if (lenid == -1)
keepdata = 0;
timeid = -1;
tid = -1;
if ((TimeInfo->isWithinPeriod(year, step)) && (keepdata == 1)) {
//if this is a new tagging exp. then resize
for (i = 0; i < tagnames.Size(); i++)
if (strcasecmp(tagnames[i], tmptagid) == 0)
tid = i;
if (tid == -1) {
//if this is a new tagging experiment, resize to store the data
tagName = new char[strlen(tmptagid) + 1];
strcpy(tagName, tmptagid);
tagnames.resize(tagName);
tid = tagnames.Size() - 1;
obsYears.AddRows(1, 1, year);
obsSteps.AddRows(1, 1, step);
timeid = 0;
obsDistribution.resize();
obsDistribution[tid].resize(new DoubleMatrix(numarea, numlen, 0.0));
modelDistribution.resize();
modelDistribution[tid].resize(new DoubleMatrix(numarea, numlen, 0.0));
//JMB - add objects to allow for timesteps when no recpatures are found
modYears.AddRows(1, 0, 0);
modSteps.AddRows(1, 0, 0);
newDistribution.resize();
} else {
for (i = 0; i < obsYears[tid].Size(); i++)
if ((obsYears[tid][i] == year) && (obsSteps[tid][i] == step))
timeid = i;
//if this is a new timestep, resize to store the data
if (timeid == -1) {
obsYears[tid].resize(1, year);
obsSteps[tid].resize(1, step);
timeid = obsYears.Ncol(tid) - 1;
obsDistribution[tid].resize(new DoubleMatrix(numarea, numlen, 0.0));
modelDistribution[tid].resize(new DoubleMatrix(numarea, numlen, 0.0));
}
}
//finally store the number of the obsDistribution
count++;
(*obsDistribution[tid][timeid])[areaid][lenid] = tmpnumber;
} else
reject++; //count number of rejected data points read from file
}
if (count == 0)
handle.logMessage(LOGWARN, "Warning in recaptures - found no data in the data file for", this->getName());
if (reject != 0)
handle.logMessage(LOGMESSAGE, "Discarded invalid recaptures data - number of invalid entries", reject);
handle.logMessage(LOGMESSAGE, "Read recaptures data file - number of entries", count);
}
Recaptures::~Recaptures() {
int i, j;
for (i = 0; i < fleetnames.Size(); i++)
delete[] fleetnames[i];
for (i = 0; i < areaindex.Size(); i++)
delete[] areaindex[i];
for (i = 0; i < lenindex.Size(); i++)
delete[] lenindex[i];
for (i = 0; i < tagnames.Size(); i++)
delete[] tagnames[i];
for (i = 0; i < obsDistribution.Nrow(); i++) {
for (j = 0; j < obsDistribution.Ncol(i); j++) {
delete obsDistribution[i][j];
delete modelDistribution[i][j];
}
}
for (i = 0; i < newDistribution.Nrow(); i++)
for (j = 0; j < newDistribution.Ncol(i); j++)
delete newDistribution[i][j];
if (aggregator != 0) {
for (i = 0; i < tagvec.Size(); i++)
delete aggregator[i];
delete[] aggregator;
aggregator = 0;
}
delete[] functionname;
}
void Recaptures::Reset(const Keeper* const keeper) {
int i, j;
Likelihood::Reset(keeper);
for (i = 0; i < newDistribution.Nrow(); i++)
for (j = 0; j < newDistribution.Ncol(i); j++)
delete newDistribution[i][j];
for (i = 0; i < modelDistribution.Nrow(); i++)
for (j = 0; j < modelDistribution.Ncol(i); j++)
(*modelDistribution[i][j]).setToZero();
if (handle.getLogLevel() >= LOGMESSAGE)
handle.logMessage(LOGMESSAGE, "Reset recaptures component", this->getName());
}
void Recaptures::setFleetsAndStocks(FleetPtrVector& Fleets, StockPtrVector& Stocks) {
int i, j, k, l, found;
FleetPtrVector fleets;
StockPtrVector stocks;
CharPtrVector stocknames;
for (i = 0; i < fleetnames.Size(); i++) {
found = 0;
for (j = 0; j < Fleets.Size(); j++)
if (strcasecmp(fleetnames[i], Fleets[j]->getName()) == 0) {
found++;
fleets.resize(Fleets[j]);
}
if (found == 0)
handle.logMessage(LOGFAIL, "Error in recaptures - failed to match fleet", fleetnames[i]);
}
for (i = 0; i < fleets.Size(); i++)
for (j = 0; j < fleets.Size(); j++)
if ((strcasecmp(fleets[i]->getName(), fleets[j]->getName()) == 0) && (i != j))
handle.logMessage(LOGFAIL, "Error in recaptures - repeated fleet", fleets[i]->getName());
double minlen, maxlen;
int minage, maxage, size;
aggregator = new RecAggregator*[tagvec.Size()];
for (k = 0; k < tagvec.Size(); k++) {
stocknames = tagvec[k]->getStockNames();
for (i = 0; i < stocknames.Size(); i++) {
found = 0;
for (j = 0; j < Stocks.Size(); j++) {
if (Stocks[j]->isEaten()) {
if (strcasecmp(stocknames[i], Stocks[j]->getName()) == 0) {
found++;
stocks.resize(Stocks[j]);
}
}
}
if (found == 0)
handle.logMessage(LOGFAIL, "Error in recaptures - failed to match stock", stocknames[i]);
}
//Check the stock has been tagged
for (j = 0; j < stocks.Size(); j++)
if (!stocks[j]->isTagged())
handle.logMessage(LOGFAIL, "Error in recaptures - stocks hasnt been tagged", stocks[j]->getName());
//Check if the stock lives on all the areas that were read in
for (i = 0; i < areas.Nrow(); i++)
for (l = 0; l < areas.Ncol(i); l++)
for (j = 0; j < stocks.Size(); j++)
if (!stocks[j]->isInArea(areas[i][l]))
handle.logMessage(LOGFAIL, "Error in recaptures - stocks arent defined on all areas");
IntMatrix agematrix(1, 0, 0);
minage = 999;
maxage = 0;
for (i = 0; i < stocks.Size(); i++) {
minage = min(stocks[i]->minAge(), minage);
maxage = max(stocks[i]->maxAge(), maxage);
}
for (i = 0; i <= maxage - minage; i++)
agematrix[0].resize(1, minage + i);
LengthGroupDivision* lgrpdiv = new LengthGroupDivision(lengths);
if (lgrpdiv->Error())
handle.logMessage(LOGFAIL, "Error in recaptures - failed to create length group");
aggregator[k] = new RecAggregator(fleets, stocks, lgrpdiv, areas, agematrix, tagvec[k]);
delete lgrpdiv;
stocks.Reset();
}
}
void Recaptures::addLikelihood(const TimeClass* const TimeInfo) {
double l = 0.0;
switch (functionnumber) {
case 1:
l = calcLikPoisson(TimeInfo);
break;
default:
handle.logMessage(LOGWARN, "Warning in recaptures - unrecognised function", functionname);
break;
}
if (!(isZero(l))) {
likelihood += l;
if (handle.getLogLevel() >= LOGMESSAGE)
handle.logMessage(LOGMESSAGE, "The likelihood score for this component on this timestep is", l);
}
}
double Recaptures::calcLikPoisson(const TimeClass* const TimeInfo) {
double x, n, lik, total;
int t, a, ti, len, timeid, checktag, checktime;
int year = TimeInfo->getYear();
int step = TimeInfo->getStep();
total = 0.0;
for (t = 0; t < tagvec.Size(); t++) {
checktag = 0;
lik = 0.0;
if (tagvec[t]->isWithinPeriod(year, step)) {
if (!checktag) {
if (handle.getLogLevel() >= LOGMESSAGE)
handle.logMessage(LOGMESSAGE, "Calculating likelihood score for recaptures component", this->getName());
checktag++;
}
aggregator[t]->Sum();
alptr = &aggregator[t]->getSum();
checktime = 0;
timeid = -1;
for (ti = 0; ti < obsYears.Ncol(t); ti++)
if ((obsYears[t][ti] == year) && (obsSteps[t][ti] == step))
timeid = ti;
if (timeid == -1) {
// this is a modelled return that doesnt have a corresponding observed return
checktime++;
for (ti = 0; ti < modYears.Ncol(t); ti++)
if ((modYears[t][ti] == year) && (modSteps[t][ti] == step))
timeid = ti;
// resize objects if needed
if (timeid == -1) {
modYears[t].resize(1, year);
modSteps[t].resize(1, step);
timeid = modYears.Ncol(t) - 1;
newDistribution[t].resize(new DoubleMatrix(areaindex.Size(), lenindex.Size(), 0.0));
}
}
for (a = 0; a < areas.Nrow(); a++) {
for (len = 0; len < lengths.Size() - 1; len++) {
x = ((*alptr)[a][0][len]).N;
if (!checktime) {
// this is a modelled return that has a non-zero observed return
n = (*obsDistribution[t][timeid])[a][len];
(*modelDistribution[t][timeid])[a][len] = x;
} else {
// this is a modelled return that doesnt have a corresponding observed return
n = 0.0;
(*newDistribution[t][timeid])[a][len] = x;
}
if (isZero(n))
lik += x;
else if (x < verysmall)
lik += verybig;
else
lik -= -x + (n * log(x)) - logFactorial(n);
}
}
}
total += lik;
}
return total;
}
void Recaptures::Print(ofstream& outfile) const {
int t, ti, area, len;
outfile << "\nRecaptures Data " << this->getName() << " - likelihood value " << likelihood
<< "\n\tFunction " << functionname << endl;
for (t = 0; t < tagvec.Size(); t++) {
outfile << "\tTagging experiment:\t" << tagnames[t];
for (ti = 0; ti < obsYears.Ncol(t); ti++) {
outfile << "\n\tyear " << obsYears[t][ti] << " and step " << obsSteps[t][ti] << "\n\tobserved recaptures";
for (area = 0; area < (*obsDistribution[t][ti]).Nrow(); area++)
for (len = 0; len < (*obsDistribution[t][ti]).Ncol(area); len++)
outfile << TAB << (*obsDistribution[t][ti])[area][len];
outfile << "\n\tmodelled recaptures";
for (area = 0; area < (*modelDistribution[t][ti]).Nrow(); area++)
for (len = 0; len < (*modelDistribution[t][ti]).Ncol(area); len++)
outfile << TAB << (*modelDistribution[t][ti])[area][len];
}
outfile << endl;
}
outfile.flush();
}
void Recaptures::printSummary(ofstream& outfile) {
//JMB to start with just print a summary of all likelihood scores
//This needs to be changed to print something for each timestep and area
//but we need to sort out how to get the information in the same format as other components
if (!(isZero(likelihood))) {
outfile << "all all all" << sep << setw(largewidth) << this->getName() << sep
<< setprecision(smallprecision) << setw(smallwidth) << weight << sep
<< setprecision(largeprecision) << setw(largewidth) << likelihood << endl;
outfile.flush();
}
}
void Recaptures::printLikelihood(ofstream& outfile, const TimeClass* const TimeInfo) {
int year = TimeInfo->getYear();
int step = TimeInfo->getStep();
int t, ti, timeid, area, len;
for (t = 0; t < tagvec.Size(); t++) {
if (tagvec[t]->isWithinPeriod(year, step)) {
timeid = -1;
for (ti = 0; ti < obsYears.Ncol(t); ti++)
if (obsYears[t][ti] == year && obsSteps[t][ti] == step)
timeid = ti;
if (timeid > -1) {
for (area = 0; area < modelDistribution[t][timeid]->Nrow(); area++) {
for (len = 0; len < modelDistribution[t][timeid]->Ncol(area); len++) {
outfile << setw(printwidth) << tagnames[t] << sep << setw(lowwidth)
<< obsYears[t][timeid] << sep << setw(lowwidth) << obsSteps[t][timeid] << sep
<< setw(printwidth) << areaindex[area] << sep << setw(printwidth)
<< lenindex[len] << sep << setprecision(largeprecision) << setw(largewidth);
//JMB crude filter to remove the 'silly' values from the output
if ((*modelDistribution[t][timeid])[area][len] < rathersmall)
outfile << 0 << endl;
else
outfile << (*modelDistribution[t][timeid])[area][len] << endl;
}
}
} else {
for (ti = 0; ti < modYears.Ncol(t); ti++)
if ((modYears[t][ti] == year) && (modSteps[t][ti] == step))
timeid = ti;
if (timeid > -1) {
for (area = 0; area < newDistribution[t][timeid]->Nrow(); area++) {
for (len = 0; len < newDistribution[t][timeid]->Ncol(area); len++) {
outfile << setw(printwidth) << tagnames[t] << sep << setw(lowwidth)
<< modYears[t][timeid] << sep << setw(lowwidth) << modSteps[t][timeid] << sep
<< setw(printwidth) << areaindex[area] << sep << setw(printwidth)
<< lenindex[len] << sep << setprecision(largeprecision) << setw(largewidth);
//JMB crude filter to remove the 'silly' values from the output
if ((*newDistribution[t][timeid])[area][len] < rathersmall)
outfile << 0 << endl;
else
outfile << (*newDistribution[t][timeid])[area][len] << endl;
}
}
}
}
}
}
}