Commit 973b7cf8 authored by Bas van der Tol's avatar Bas van der Tol

Add BDAPredict step

parent 3ecab147
Pipeline #11708 failed with stages
in 45 minutes and 53 seconds
......@@ -324,6 +324,7 @@ add_library(DP3_OBJ OBJECT
steps/OneApplyCal.cc
steps/PhaseShift.cc
steps/Predict.cc
steps/BDAPredict.cc
steps/PreFlagger.cc
steps/ScaleData.cc
steps/SetBeam.cc
......
......@@ -332,62 +332,62 @@ Step::ShPtr DP3::makeSingleStep(const std::string& type, InputStep* inputStep,
const std::string& prefix, std::string& msName,
Step::MSType inputType) {
if (type == "aoflagger" || type == "aoflag") {
return steps::Step::CreateInstance<steps::AOFlaggerStep>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::AOFlaggerStep>(inputStep, parset, prefix, inputType);
} else if (type == "averager" || type == "average" || type == "squash") {
return steps::Step::CreateInstance<steps::Averager>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::Averager>(inputStep, parset, prefix, inputType);
} else if (type == "bdaaverager") {
return steps::Step::CreateInstance<steps::BDAAverager>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::BDAAverager>(inputStep, parset, prefix, inputType);
} else if (type == "madflagger" || type == "madflag") {
return steps::Step::CreateInstance<steps::MedFlagger>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::MedFlagger>(inputStep, parset, prefix, inputType);
} else if (type == "preflagger" || type == "preflag") {
return steps::Step::CreateInstance<steps::PreFlagger>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::PreFlagger>(inputStep, parset, prefix, inputType);
} else if (type == "uvwflagger" || type == "uvwflag") {
return steps::Step::CreateInstance<steps::UVWFlagger>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::UVWFlagger>(inputStep, parset, prefix, inputType);
} else if (type == "columnreader") {
return steps::Step::CreateInstance<steps::ColumnReader>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::ColumnReader>(inputStep, parset, prefix, inputType);
} else if (type == "counter" || type == "count") {
return steps::Step::CreateInstance<steps::Counter>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::Counter>(inputStep, parset, prefix, inputType);
} else if (type == "phaseshifter" || type == "phaseshift") {
return steps::Step::CreateInstance<steps::PhaseShift>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::PhaseShift>(inputStep, parset, prefix, inputType);
} else if (type == "demixer" || type == "demix") {
return steps::Step::CreateInstance<steps::Demixer>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::Demixer>(inputStep, parset, prefix, inputType);
} else if (type == "smartdemixer" || type == "smartdemix") {
return steps::Step::CreateInstance<steps::DemixerNew>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::DemixerNew>(inputStep, parset, prefix, inputType);
} else if (type == "applybeam") {
return steps::Step::CreateInstance<steps::ApplyBeam>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::ApplyBeam>(inputStep, parset, prefix, inputType);
} else if (type == "stationadder" || type == "stationadd") {
return steps::Step::CreateInstance<steps::StationAdder>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::StationAdder>(inputStep, parset, prefix, inputType);
} else if (type == "scaledata") {
return steps::Step::CreateInstance<steps::ScaleData>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::ScaleData>(inputStep, parset, prefix, inputType);
} else if (type == "setbeam") {
return steps::Step::CreateInstance<steps::SetBeam>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::SetBeam>(inputStep, parset, prefix, inputType);
} else if (type == "filter") {
return steps::Step::CreateInstance<steps::Filter>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::Filter>(inputStep, parset, prefix, inputType);
} else if (type == "applycal" || type == "correct") {
return steps::Step::CreateInstance<steps::ApplyCal>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::ApplyCal>(inputStep, parset, prefix, inputType);
} else if (type == "predict") {
return steps::Step::CreateInstance<steps::Predict>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::Predict>(inputStep, parset, prefix, inputType);
} else if (type == "idgpredict") {
return steps::Step::CreateInstance<steps::IDGPredict>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::IDGPredict>(inputStep, parset, prefix, inputType);
} else if (type == "h5parmpredict") {
return steps::Step::CreateInstance<steps::H5ParmPredict>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::H5ParmPredict>(inputStep, parset, prefix, inputType);
} else if (type == "gaincal" || type == "calibrate") {
return steps::Step::CreateInstance<steps::GainCal>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::GainCal>(inputStep, parset, prefix, inputType);
} else if (type == "upsample") {
return steps::Step::CreateInstance<steps::Upsample>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::Upsample>(inputStep, parset, prefix, inputType);
} else if (type == "split" || type == "explode") {
return steps::Step::CreateInstance<steps::Split>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::Split>(inputStep, parset, prefix, inputType);
} else if (type == "ddecal") {
return steps::Step::CreateInstance<steps::DDECal>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::DDECal>(inputStep, parset, prefix, inputType);
} else if (type == "interpolate") {
return steps::Step::CreateInstance<steps::Interpolate>(inputStep, parset, prefix);
return steps::Step::CreateInstance<steps::Interpolate>(inputStep, parset, prefix, inputType);
} else if (type == "out" || type == "output" || type == "msout") {
if (msName.empty())
msName = casacore::Path(inputStep->msName()).absoluteName();
return makeOutputStep(inputStep, parset, prefix, msName,
inputType == Step::MSType::BDA);
} else if (type == "python" || type == "pythondppp") {
return steps::Step::CreateInstance<pythondp3::PyStep>(inputStep, parset, prefix);
return steps::Step::CreateInstance<pythondp3::PyStep>(inputStep, parset, prefix, inputType);
} else {
// Maybe the step is defined in a dynamic library.
return findStepCtor(type)(inputStep, parset, prefix);
......
......@@ -88,7 +88,7 @@ void PyStepImpl::hold() {
namespace steps {
template<>
steps::Step::ShPtr steps::Step::CreateInstance<pythondp3::PyStep>(InputStep* input, const common::ParameterSet& parset, const string& prefix) {
steps::Step::ShPtr steps::Step::CreateInstance<pythondp3::PyStep>(InputStep* input, const common::ParameterSet& parset, const string& prefix, Step::MSType) {
std::string module_name = parset.getString(prefix + "python.module");
std::string class_name = parset.getString(prefix + "python.class");
......
......@@ -18,7 +18,7 @@ class PyStep : public steps::Step {
namespace steps {
template<>
Step::ShPtr Step::CreateInstance<pythondp3::PyStep>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix);
Step::ShPtr Step::CreateInstance<pythondp3::PyStep>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType inputType);
} // namespace steps
} // namespace dp3
......
......@@ -22,7 +22,7 @@ namespace dp3 {
namespace steps {
template<>
Step::ShPtr Step::CreateInstance<BDAAverager>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix) {
Step::ShPtr Step::CreateInstance<BDAAverager>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType) {
return std::make_shared<BDAAverager>(*input, parameterset, prefix);
}
......@@ -219,9 +219,9 @@ bool BDAAverager::process(const DPBuffer& buffer) {
bb_weights += info().ncorr();
}
bb.uvw[0] += uvw(0, b) * total_weight;
bb.uvw[1] += uvw(1, b) * total_weight;
bb.uvw[2] += uvw(2, b) * total_weight;
bb.uvw[0] += uvw(0, b);
bb.uvw[1] += uvw(1, b);
bb.uvw[2] += uvw(2, b);
if (bb.times_added == bb.time_factor) {
AddBaseline(b); // BaselineBuffer is complete: Add it.
......@@ -274,7 +274,7 @@ void BDAAverager::AddBaseline(std::size_t baseline_nr) {
}
if (total_weight > 0) {
const double factor = 1.0 / total_weight;
const double factor = 1.0 / bb.times_added;
bb.uvw[0] *= factor;
bb.uvw[1] *= factor;
bb.uvw[2] *= factor;
......
......@@ -100,7 +100,7 @@ class BDAAverager : public Step {
};
template<>
Step::ShPtr Step::CreateInstance<BDAAverager>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix);
Step::ShPtr Step::CreateInstance<BDAAverager>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType inputType);
} // namespace steps
} // namespace dp3
......
// BDAPredict.cc: DPPP step class to BDAPredict visibilities
// Copyright (C) 2021 ASTRON (Netherlands Institute for Radio Astronomy)
// SPDX-License-Identifier: GPL-3.0-or-later
//
// @author Sebastiaan van der Tol
#include "BDAPredict.h"
#include "Predict.h"
#include <iostream>
#include "../common/ParameterSet.h"
#include "../common/Timer.h"
#include <stddef.h>
#include <string>
#include <sstream>
#include <utility>
#include <vector>
using dp3::base::BDABuffer;
using dp3::base::DPInfo;
namespace dp3 {
namespace steps {
// Simple InputStep class to forward data.
class ForwardInput : public InputStep {
public:
virtual bool process(const base::DPBuffer &buffer) {
getNextStep()->process(buffer);
return true;
}
virtual void finish() { getNextStep()->finish(); }
virtual void show(std::ostream&) const {}
};
// class representing a group of baselines that have the same averaging / data shape
class BDAPredict::BaselineGroup {
public:
void AddBaseline(int bl) {
itsBaselines.push_back(bl);
}
int GetSize() const {return itsBaselines.size();}
void MakeSteps(base::DPInfo &info_in, const common::ParameterSet &parset, std::string &prefix) {
itsInputStep = std::make_shared<ForwardInput>();
itsPredictStep = std::make_shared<Predict>(itsInputStep.get(), parset, prefix);
itsResultStep = std::make_shared<ResultStep>();
itsInputStep->setNextStep(itsPredictStep);
itsPredictStep->setNextStep(itsResultStep);
DPInfo info(info_in);
int nbaselines = itsBaselines.size();
casacore::Vector<casacore::Int> ant1(nbaselines), ant2(nbaselines);
for(int bl_idx=0; bl_idx<nbaselines; ++bl_idx) {
ant1(bl_idx) = info_in.getAnt1()[itsBaselines[bl_idx]];
ant2(bl_idx) = info_in.getAnt2()[itsBaselines[bl_idx]];
}
if (nbaselines == 1){
std::cout << itsBaselines[0] << std::endl;
std::cout << ant1 << std::endl;
std::cout << ant2 << std::endl;
}
itsWriteBackPtrs.resize(nbaselines);
info.set(
info_in.antennaNames(),
info_in.antennaDiam(),
info_in.antennaPos(),
ant1,
ant2);
info.setNThreads(1);
// std::vector<double> chanFreqs(info_in.chanFreqs(itsBaselines[0]));
std::vector<double> chanFreqs(info_in.chanFreqs(itsBaselines[0]).size(), 130e6);
std::vector<double> chanWidths(info_in.chanWidths(itsBaselines[0]));
int nchan = chanFreqs.size();
info.set(
std::move(chanFreqs),
std::move(chanWidths)); // This does not update info.nchan() !!
info.setNChan(nchan); // So we need to set it
itsInputStep->setInfo(info);
itsData.resize(info_in.ncorr(), nchan, nbaselines);
itsWeights.resize(info_in.ncorr(), nchan, nbaselines);
itsFlags.resize(info_in.ncorr(), nchan, nbaselines);
itsUVW.resize(3, nbaselines);
itsDPBuffer.setData(itsData);
itsDPBuffer.setWeights(itsWeights);
itsDPBuffer.setFlags(itsFlags);
itsDPBuffer.setUVW(itsUVW);
itsPredictStep->show(std::cout);
}
void ProcessRow(const base::BDABuffer::Row &row, int bl_idx) {
double time = row.time + row.interval/2;
if (itsNBaselinesRequested && (abs(itsDPBuffer.getTime() - time) > 1e-3)) {
Flush();
}
int n_elements = row.n_channels * row.n_correlations;
std::copy(row.uvw, row.uvw + 3, itsUVW[bl_idx].begin());
std::copy(row.data, row.data + n_elements, itsData[bl_idx].begin());
std::copy(row.weights, row.weights + n_elements, itsWeights[bl_idx].begin());
std::copy(row.flags, row.flags + n_elements, itsFlags[bl_idx].begin());
itsWriteBackPtrs[bl_idx] = row.data;
itsDPBuffer.setTime(time);
int nbaselines = (int)itsBaselines.size();
if (++itsNBaselinesRequested == nbaselines) {
Flush();
}
}
void Flush() {
if (!itsNBaselinesRequested) return;
itsInputStep->process(itsDPBuffer);
base::DPBuffer &buf_out = itsResultStep->get();
int nbaselines = (int)itsBaselines.size();
for(int bl=0; bl<nbaselines; ++bl){
if (itsWriteBackPtrs[bl]) {
if (itsBaselines[bl] == 19) {
std::cout << buf_out.getData()(0,0,bl) << std::endl;
}
std::copy(buf_out.getData()[bl].begin(), buf_out.getData()[bl].end(), itsWriteBackPtrs[bl]);
// itsWriteBackPtrs[bl][0] = buf_out.getUVW()(0,bl);
// itsWriteBackPtrs[bl][1] = buf_out.getUVW()(1,bl);
// itsWriteBackPtrs[bl][2] = buf_out.getUVW()(2,bl);
// itsWriteBackPtrs[bl][3] = buf_out.getTime();
}
}
itsNBaselinesRequested = 0;
std::fill(itsWriteBackPtrs.begin(), itsWriteBackPtrs.end(), nullptr);
}
private:
std::vector<int> itsBaselines;
std::shared_ptr<InputStep> itsInputStep;
std::shared_ptr<Predict> itsPredictStep;
std::shared_ptr<ResultStep> itsResultStep;
base::DPBuffer itsDPBuffer;
std::vector<std::complex<float>*> itsWriteBackPtrs;
casacore::Cube<casacore::Complex> itsData;
casacore::Cube<float> itsWeights;
casacore::Cube<bool> itsFlags;
casacore::Matrix<double> itsUVW;
int itsNBaselinesRequested;
};
BDAPredict::BDAPredict(InputStep* input, const common::ParameterSet& parset,
const string& prefix)
: itsInput(input),
itsParset(parset),
itsName(prefix) {}
BDAPredict::~BDAPredict() {}
void BDAPredict::updateInfo(const DPInfo& infoIn) {
info() = infoIn;
info().setNeedVisData();
info().setWriteData();
for(int bl = 0; bl < (int)info().nbaselines(); ++bl) {
auto averaging_key = std::make_pair(info().ntimeAvg(bl), info().chanFreqs(bl).size());
BaselineGroup &blg = itsAveragingToBaselineGroupMap[averaging_key];
int idx_in_blg = blg.GetSize();
blg.AddBaseline(bl);
itsIndexToBaselineGroupMap.push_back(std::make_pair(&blg, idx_in_blg));
}
for (auto &entry : itsAveragingToBaselineGroupMap) {
BaselineGroup &blg = entry.second;
blg.MakeSteps(info(), itsParset, itsName);
}
}
void BDAPredict::show(std::ostream& os) const {
os << "BDAPredict " << itsName << '\n';
int nr_chan_configs = getInfo().hasBDAChannels() ? getInfo().nbaselines() : 1;
}
void BDAPredict::showTimings(std::ostream& os, double duration) const {
os << " ";
base::FlagCounter::showPerc1(os, itsTimer.getElapsed(), duration);
os << " BDAPredict " << itsName << '\n';
}
bool BDAPredict::process(std::unique_ptr<base::BDABuffer> buffer) {
itsTimer.start();
// itsBuffer.copy(bufin);
// itsInput->fetchUVW(bufin, itsBuffer, itsTimer);
// itsInput->fetchWeights(bufin, itsBuffer, itsTimer);
const std::vector<base::BDABuffer::Row> &rows = buffer->GetRows();
for(auto const &row : rows) {
BaselineGroup &blg = *itsIndexToBaselineGroupMap[row.baseline_nr].first;
int bl_in_group_idx = itsIndexToBaselineGroupMap[row.baseline_nr].second;
blg.ProcessRow(row, bl_in_group_idx);
}
for (auto &entry : itsAveragingToBaselineGroupMap) {
BaselineGroup &blg = entry.second;
blg.Flush();
}
itsTimer.stop();
getNextStep()->process(std::move(buffer));
return false;
}
void BDAPredict::finish() {
// Let the next steps finish.
getNextStep()->finish();
}
} // namespace steps
} // namespace dp3
// BDAPredict.h: class to directly predict baseline dependent averaged (BDA)
// visibilities from a source model
// Copyright (C) 2020 ASTRON (Netherlands Institute for Radio Astronomy)
// SPDX-License-Identifier: GPL-3.0-or-later
/// @file
/// @brief DPPP step class to DummyStep visibilities from a source model
/// @author Sebastiaan van der Tol
#ifndef DPPP_BDAPredict_H
#define DPPP_BDAPredict_H
#include "InputStep.h"
#include "../base/BDABuffer.h"
#include <utility>
namespace dp3 {
namespace common {
class ParameterSet;
}
namespace steps {
/// @brief
/// This class is an empty Step subclass to use as implementation template
class BDAPredict : public Step {
public:
/// Construct the object.
/// Parameters are obtained from the parset using the given prefix.
BDAPredict(InputStep*, const common::ParameterSet&, const string& prefix);
virtual ~BDAPredict();
/// Process the data.
/// It keeps the data.
/// When processed, it invokes the process function of the next step.
bool process(std::unique_ptr<base::BDABuffer>) override;
/// Finish the processing of this step and subsequent steps.
void finish() override;
/// Update the general info.
void updateInfo(const base::DPInfo&) override;
/// Show the step parameters.
void show(std::ostream&) const override;
/// Show the timings.
void showTimings(std::ostream&, double duration) const override;
/// Boolean if this step can process this type of data.
virtual bool accepts(MSType dt) const override { return dt == BDA; }
/// Return which datatype this step outputs.
MSType outputs() const override { return BDA; }
private:
InputStep* itsInput;
const common::ParameterSet& itsParset;
std::string itsName;
class BaselineGroup;
std::map<std::pair<int,int>, BaselineGroup> itsAveragingToBaselineGroupMap;
std::vector<std::pair<BaselineGroup*, int>> itsIndexToBaselineGroupMap;
common::NSTimer itsTimer;
};
} // namespace steps
} // namespace dp3
#endif
......@@ -14,7 +14,7 @@ namespace dp3 {
namespace steps {
template<>
Step::ShPtr Step::CreateInstance<ColumnReader>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix) {
Step::ShPtr Step::CreateInstance<ColumnReader>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType) {
return std::make_shared<ColumnReader>(*input, parameterset, prefix);
}
......
......@@ -43,7 +43,7 @@ class ColumnReader : public Step {
};
template<>
Step::ShPtr Step::CreateInstance<ColumnReader>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix);
Step::ShPtr Step::CreateInstance<ColumnReader>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType inputType);
} // namespace steps
} // namespace dp3
......
// DummyStep.h: DPPP step class to DummyStep visibilities from a source model
// DummyStep.h: empty Step subclass to use as implementation template
// Copyright (C) 2020 ASTRON (Netherlands Institute for Radio Astronomy)
// SPDX-License-Identifier: GPL-3.0-or-later
......@@ -21,8 +21,7 @@ class ParameterSet;
}
namespace steps {
/// @brief DPPP step class to DummyStep visibilities from a source model
/// @brief dummy Step
/// This class is an empty Step subclass to use as implementation template
class DummyStep : public Step {
......
......@@ -41,7 +41,7 @@ namespace dp3 {
namespace steps {
template<>
Step::ShPtr Step::CreateInstance<IDGPredict>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix) {
Step::ShPtr Step::CreateInstance<IDGPredict>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType) {
return std::make_shared<IDGPredict>(*input, parameterset, prefix);
}
......
......@@ -178,7 +178,7 @@ class IDGPredict : public Step {
};
template<>
Step::ShPtr Step::CreateInstance<IDGPredict>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix);
Step::ShPtr Step::CreateInstance<IDGPredict>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType inputType);
} // namespace steps
} // namespace dp3
......
......@@ -5,6 +5,7 @@
// @author Tammo Jan Dijkema
#include "Predict.h"
#include "BDAPredict.h"
#include "ApplyBeam.h"
#include <iostream>
......@@ -63,9 +64,9 @@ namespace dp3 {
namespace steps {
template<>
Step::ShPtr Step::CreateInstance<Predict>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix) {
if (input->outputs() == Step::MSType::BDA) {
return std::make_shared<Predict>(input, parameterset, prefix);
Step::ShPtr Step::CreateInstance<Predict>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType inputType) {
if (inputType == Step::MSType::BDA) {
return std::make_shared<BDAPredict>(input, parameterset, prefix);
} else{
return std::make_shared<Predict>(input, parameterset, prefix);
}
......@@ -259,11 +260,12 @@ void Predict::updateInfo(const DPInfo& infoIn) {
itsMovingPhaseRef = false;
itsPhaseRef =
base::Position(angles.getBaseValue()[0], angles.getBaseValue()[1]);
std::cout << ">>>" << angles.getBaseValue()[0] << ", " << angles.getBaseValue()[1] << std::endl;
} catch (casacore::AipsError&) {
// Phase direction (in J2000) is time dependent
itsMovingPhaseRef = true;
}
initializeThreadData();
if (itsDoApplyCal) {
......@@ -324,6 +326,7 @@ void Predict::showTimings(std::ostream& os, double duration) const {
bool Predict::process(const DPBuffer& bufin) {
itsTimer.start();
DPBuffer tempBuffer;
tempBuffer.copy(bufin);
itsInput->fetchUVW(bufin, tempBuffer, itsTimer);
......@@ -341,6 +344,14 @@ bool Predict::process(const DPBuffer& bufin) {
base::nsplitUVW(itsUVWSplitIndex, itsBaselines, tempBuffer.getUVW(), itsUVW);
if ((nBl == 1) && (info().getAnt1()[0] == 4) && (info().getAnt2()[0] == 6)) {
std::cout << "**************" << std::endl;
std::cout << nSt << std::endl;
std::cout << itsUVW << std::endl;
std::cout << itsBaselines << std::endl;
}
double time = tempBuffer.getTime();
// Set up directions for beam evaluation
everybeam::vector3r_t refdir, tiledir;
......
......@@ -171,7 +171,7 @@ class Predict : public Step {
};
template<>
Step::ShPtr Step::CreateInstance<Predict>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix);
Step::ShPtr Step::CreateInstance<Predict>(InputStep* input, const common::ParameterSet& parameterset, const string& prefix, Step::MSType inputType);