void testRoi() { using namespace vigra; typedef ChannelSelector<4, float>::V V; typedef vigra::TinyVector<int, 4> V4; int ch = 0; MultiArray<4, float> data(vigra::TinyVector<int, 4>(10,20,30,2)); FillRandom<float, float*>::fillRandom(data.data(), data.data()+data.size()); { HDF5File f("test.h5", HDF5File::Open); f.write("test", data); } SourceHDF5<4, float> source("test.h5", "test"); source.setRoi(Roi<4>(V4(1,3,5,0), V4(7,9,30,2))); SinkHDF5<3, float> sink("channel.h5", "channel"); ChannelSelector<4, float> cs(&source, V(10,10,10)); cs.run(3, ch, &sink); HDF5File f("channel.h5", HDF5File::Open); MultiArray<3, float> r; f.readAndResize("channel", r); MultiArrayView<3, float> shouldResult = data.bind<3>(ch).subarray(V(1,3,5), V(7,9,30)); shouldEqualSequence(r.begin(), r.end(), shouldResult.begin()); }
Fields FieldAlgorithms::fieldsByLaplasian(MultiArray<2, float> & image) { MultiArray<2, float> valley(image.shape()); Pyramid pyramid(image); for (int i = 3; i > 0; i--) { MultiArray<2, float> resized(pyramid.get(i)); MultiArray<2, float> tmpArr(resized.shape()); laplacianOfGaussianMultiArray(resized, tmpArr, 1.0); valley += pyramid.toOriginalSize(tmpArr); } MultiArray<2, float> peak = valley * -1; //remove DC component float thrhld = valley[argMax(valley)] * 0.3; threshold(valley, valley, thrhld); thrhld = peak[argMax(peak)] * 0.3; threshold(peak, peak, thrhld); //Edge as Gradients MultiArray<2, float> edgeField(image.shape()); gaussianGradientMagnitude(image, edgeField, 1.0); //Localize std::vector<Shape2> valleyLocals(localizePOI(image)); //Result as Field Object Fields fields(valley, valleyLocals, peak, edgeField, image); //A heuristic initialization of the localization, as a priori known position Shape2 nextToIris = Shape2(image.width() / 2, image.height() / 2); fields.specializedIrisValley = localizeByFollowingLocalMaxima(image, nextToIris); return fields; }
void test() { using namespace vigra; typedef ChannelSelector<4, float>::V V; for(int ch=0; ch<=1; ++ch) { std::cout << "* channel = " << ch << std::endl; MultiArray<4, float> data(vigra::TinyVector<int, 4>(10,20,30,2)); FillRandom<float, float*>::fillRandom(data.data(), data.data()+data.size()); { HDF5File f("test.h5", HDF5File::Open); f.write("test", data); } SourceHDF5<4, float> source("test.h5", "test"); SinkHDF5<3, float> sink("channel.h5", "channel"); sink.setBlockShape(V(10,10,10)); ChannelSelector<4, float> cs(&source, V(10,10,10)); cs.run(3, ch, &sink); HDF5File f("channel.h5", HDF5File::Open); MultiArray<3, float> r; f.readAndResize("channel", r); MultiArrayView<3, float> shouldResult = data.bind<3>(ch); shouldEqualSequence(r.begin(), r.end(), shouldResult.begin()); } //loop through channels }
std::vector<Shape2> FieldAlgorithms::localizePOIExample(const MultiArray<2, float> &image, MultiArray<2, RGBValue<UInt8> > &rgb_array) { std::vector<Shape2> pois(30); float thld = image[argMax(image)] * 0.2; for (int i = 0; i < pois.size(); i++) { int v1 = std::rand() % image.size() -1; // v1 in the range 0 to image.size() Shape2 poi(image.scanOrderIndexToCoordinate(v1)); poi = localizeByFollowingLocalMaxima(image, poi); if (image[poi] > thld) { pois[i] = poi; MultiArrayView<2, RGBValue<UInt8> > markAsStep(rgb_array.subarray(Shape2(poi[0] - 5, poi[1] -5), Shape2(poi[0] +5, poi[1] +5))); for (RGBValue<UInt8> & val : markAsStep) { val.setRed(200); } } else { i--; } } return pois; }
void test() { using namespace vigra; typedef Thresholding<3, float>::V V; MultiArray<3, float> data(V(24,33,40)); FillRandom<float, float*>::fillRandom(data.data(), data.data()+data.size()); { HDF5File f("test.h5", HDF5File::Open); f.write("test", data); } SourceHDF5<3, float> source("test.h5", "test"); SinkHDF5<3, vigra::UInt8> sink("thresh.h5", "thresh"); sink.setBlockShape(V(10,10,10)); Thresholding<3, float> bs(&source, V(6,4,7)); bs.run(0.5, 0, 1, &sink); HDF5File f("thresh.h5", HDF5File::Open); MultiArray<3, UInt8> r; f.readAndResize("thresh", r); MultiArray<3, UInt8> t(data.shape()); transformMultiArray(srcMultiArrayRange(data), destMultiArray(t), Threshold<float, UInt8>(-std::numeric_limits<float>::max(), 0.5, 1, 0)); shouldEqual(t.shape(), r.shape()); shouldEqualSequence(r.begin(), r.end(), t.begin()); }
MultiArray<complex<float>, 4> reconMGE(Agilent::FID &fid) { int nx = fid.procpar().realValue("np") / 2; int ny = fid.procpar().realValue("nv"); int nz = fid.procpar().realValue("nv2"); int narray = fid.procpar().realValue("arraydim"); int ne = fid.procpar().realValue("ne"); MultiArray<complex<float>, 4> vols({nx, ny, nz, narray*ne}); int vol = 0; if (verbose) cout << "Reading MGE fid" << endl; for (int a = 0; a < narray; a++) { if (verbose) cout << "Reading block " << a << endl; shared_ptr<vector<complex<float>>> block = make_shared<vector<complex<float>>>(); *block = fid.readBlock(a); int e_offset = 0; for (int e = 0; e < ne; e++) { if (verbose) cout << "Reading echo " << e << endl; MultiArray<complex<float>, 3> this_vol({nx, ny, nz}, block, {1,ne*nx,ne*nx*ny}, e_offset); MultiArray<complex<float>, 3> slice = vols.slice<3>({0,0,0,vol},{-1,-1,-1,0}); auto it1 = this_vol.begin(); auto it2 = slice.begin(); while (it1 != this_vol.end()) { *it2++ = *it1++; } vol++; e_offset += nx; } } return vols; }
Shape2 FieldAlgorithms::localizeByFollowingLocalMaxima(const MultiArray<2, float> &image, Shape2 current) { //Open viewBox of image with center at current int upperLeftX = current[0] - ((image.width() / 10) / 2); upperLeftX = upperLeftX > -1 ? upperLeftX : 0; int upperLeftY = current[1] - ((image.height() / 10) / 2); upperLeftY = upperLeftY > -1 ? upperLeftY : 0; Shape2 upperLeft(upperLeftX, upperLeftY); int lowerRightX = current[0] + ((image.width() / 10) / 2); lowerRightX = lowerRightX < image.width() ? lowerRightX : image.width() -1; int lowerRightY = current[1] + ((image.height() / 10) / 2); lowerRightY = lowerRightY < image.height() ? lowerRightY : image.height() -1; Shape2 lowerRight(lowerRightX, lowerRightY); MultiArrayView<2, float> box = image.subarray(upperLeft, lowerRight); //3: get local max of view as next int maxIndex = argMax(box); if (maxIndex == -1) { std::cout << "Something went wrong: argMax returned -1"; return current; } Shape2 max(box.scanOrderIndexToCoordinate(maxIndex)); Shape2 next(upperLeftX + max[0], upperLeftY + max[1]); if (next == current) { return next; } return localizeByFollowingLocalMaxima(image, next); }
void mark( MultiArray& m,const Sequence& pts, const point& p,int dx,int dy) { for(int k=p.x<0||p.y<0||p.x>=m.shape()[0]||p.y>=m.shape()[1]?1:0, k_end=distZ2inf(p,pts.begin(),pts.end()); k<k_end; ++k) { int x=p.x-k*dx; int y=p.y-k*dy; if(x>=0&&y>=0&&x<m.shape()[0]&&y<m.shape()[1])m[x][y]=true; } }
void fft_X(MultiArray<complex<float>, 3> &a) { FFT<float> fft; int nx = a.dims()[0]; for (int z = 0; z < a.dims()[2]; z++) { for (int y = 0; y < a.dims()[1]; y++) { VectorXcf fft_in = a.slice<1>({0,y,z},{nx,0,0}).asArray(); VectorXcf fft_out(nx); fft.fwd(fft_out, fft_in); a.slice<1>({0,y,z},{nx,0,0}).asArray() = fft_out; } } }
void fft_Y(MultiArray<complex<float>, 3> &a) { FFT<float> fft; int ny = a.dims()[1]; for (int z = 0; z < a.dims()[2]; z++) { for (int x = 0; x < a.dims()[0]; x++) { VectorXcf fft_in = a.slice<1>({x,0,z},{0,ny,0}).asArray(); VectorXcf fft_out(ny); fft.fwd(fft_out, fft_in); a.slice<1>({x,0,z},{0,ny,0}).asArray() = fft_out; } } }
void fft_Z(MultiArray<complex<float>, 3> &a) { FFT<float> fft; int nz = a.dims()[2]; for (int x = 0; x < a.dims()[0]; x++) { for (int y = 0; y < a.dims()[1]; y++) { VectorXcf fft_in = a.slice<1>({x,y,0},{0,0,nz}).asArray(); VectorXcf fft_out(nz); fft.fwd(fft_out, fft_in); a.slice<1>({x,y,0},{0,0,nz}).asArray() = fft_out; } } }
void ApplyFilter3D(MultiArray<complex<float>, 3> ks, MultiArray<float, 3> filter) { if ((ks.dims() != filter.dims()).any()) { throw(runtime_error("K-space and filter dimensions do not match.")); } auto k_it = ks.begin(); auto f_it = filter.begin(); while (k_it != ks.end()) { *k_it = (*k_it) * (*f_it); k_it++; f_it++; } }
std::vector<Shape2> FieldAlgorithms::localizePOI(MultiArray<2, float> &image) { std::vector<Shape2> pois(1); for (int i = 0; i < pois.size(); i++) { int v1 = std::rand() % image.size() -1; //int maxIndex = argMax(box); //Shape2 max(box.scanOrderIndexToCoordinate(maxIndex)); //image.scanOrderIndexToCoordinate(v1) Shape2 poi = localizeByFollowingLocalMaxima(image, Shape2(image.width()/2, image.height()/2)); pois[i] = poi; } return pois; }
Fields FieldAlgorithms::fieldsByErosionDilation(MultiArray<2, float> & image) { Shape2 shape = image.shape(); MultiArray<2, float> source(image); MultiArray<2, float> t1(shape); MultiArray<2, float> t2(shape); double radius = 9; //Sinnvoll? multiGrayscaleErosion(source, t1, radius); multiGrayscaleDilation(source, t2, radius); MultiArray<2, float> psi_e = (t1- t2) * -1; //Opening of source multiGrayscaleErosion(source, t1, radius); multiGrayscaleDilation(t1, t2, radius); MultiArray<2, float> psi_p = source - t2; MultiArray<2, float> psi_pSmooth(psi_p.shape()); gaussianSmoothMultiArray(psi_p, psi_pSmooth, 8.0); //Opening of source MultiArray<2, float> inverse = source * -1; multiGrayscaleErosion(inverse, t1, 9); multiGrayscaleDilation(t1, t2, 9); MultiArray<2, float> psi_v = t2 - inverse; MultiArray<2, float> psi_vSmooth(psi_v.shape()); gaussianSmoothMultiArray(psi_v, psi_vSmooth, 3.0); std::vector<Shape2> valleyLocals(0); Fields fields(psi_vSmooth, valleyLocals, psi_pSmooth, psi_e, image); return fields; };
// MAIN int main(int argc, char** argv) { if(argc != 3) { std::cout << "usage: " << argv[0] << " infile.sif outfile" << std::endl << std::endl; std::cout << "Converts one sif file to tiff stack" << std::endl; return 2; } std::string infile = argv[1]; std::string outfile = argv[2]; try { MultiArray<3,float> in; typedef MultiArray<3, float>::difference_type Shape; int width, height, stacksize; HDF5ImportInfo info(infile.c_str(), "/data"); width = info.shapeOfDimension(0); height = info.shapeOfDimension(1); stacksize = info.shapeOfDimension(2); // create a 3D array of appropriate size in.reshape(Shape(width,height,stacksize)); readHDF5(info, in); //Eingabe Bild std::cout << "Images with Shape: " << Shape(width, height, stacksize) << std::endl; std::cout << "Processing a stack of " << stacksize << " images..." << std::endl; exportVolume(in, VolumeExportInfo(outfile.c_str(), ".tif")); } catch (vigra::StdException & e) { std::cout<<"There was an error:"<<std::endl; std::cout << e.what() << std::endl; return 1; } }
MultiArray<2, float > FieldAlgorithms::morphologyByGradientPattern(MultiArray<2, float> & image, MultiArray<2,float> &mask) { Shape2 shape(image.shape()); MultiArray<2, TinyVector<float, 2>> imageGradients(shape); MultiArray<2, TinyVector<float, 2>> maskGradients(mask.shape()); gaussianGradientMultiArray(image, imageGradients, 2.0); gaussianGradientMultiArray(mask, maskGradients, 2.0); //Threshold gradients with small magnitude, //because we only consider directions from now on. MultiArray<2, float> magnitudes(shape); gaussianGradientMagnitude(image, magnitudes, 3.0); float thrhld = magnitudes[argMax(magnitudes)] * 0.3; thresholdGrad(magnitudes, imageGradients, thrhld); //The actual machting: return matchGradients(imageGradients, maskGradients); };
MultiArray<2, float > FieldAlgorithms::matchGradients(MultiArray<2, TinyVector<float, 2> > &imageGradients, MultiArray<2, TinyVector<float, 2> > &mask) { MultiArray<2, float > dest(imageGradients.shape()); dest = 0; //to make sure, that the mask is always fully within the image, consider the mask shape int diff = (mask.width() -1) / 2; for (int x = diff; x + diff < imageGradients.width(); x ++) { for (int y = diff; y + diff < imageGradients.height(); y++) { //The masks center is at point x,y now //Every vector of the image currently 'covered' by the mask, is compared to its corresponding vector in the mask. float vals = 0; for (int xM = 0; xM < mask.width(); xM++) { for (int yM = 0; yM < mask.height(); yM++) { TinyVector<float, 2> imageVal = imageGradients((x - diff) + xM, (y - diff) + yM); TinyVector<float, 2> maskVal = mask(xM, yM); vals += compareVectors(imageVal, maskVal); } } int res = vals / (mask.size()); dest(x,y) = res; } } return dest; };
//Calculates the fit for all radii std::vector<MultiArray<2,float>> Deformation::getFit(MultiArray<2, int> &distanceToCenter) { int length = distanceToCenter.width(); MultiArray<2,float> resEdge(Shape2(length, 1)); MultiArray<2,float> resValley(Shape2(length, 1)); MultiArray<2,float> resBoth(Shape2(length, 1)); for (int radius = 1; radius < distanceToCenter.width() / 2; radius++) { RadiusResult radi = getValueForRadius(distanceToCenter, radius); resValley[radius] = radi.valley; resBoth[radius] = radi.getValue(); resEdge[radius] = radi.edge; } std::vector<MultiArray<2,float>>result(3); result[0] = resEdge; result[1] = resValley; result[2] = resBoth; return result; }
void FieldAlgorithms::threshold(MultiArray<2, float> &basis, MultiArray<2, float> &target, float threshold) { for (int j = 0; j < basis.size(); j++) { if (basis[j] < threshold) { target[j] = 0; } } };
RadiusResult Deformation::getRadiusRecursivly(MultiArray<2, int> &distanceToCenter, RadiusResult &one, RadiusResult &two, float temperature) { if (temperature < 1) { return one; } if (one.radius == two.radius) { one.radius++; } float derivative = (one.getValue() - two.getValue()) / (one.radius - two.radius); derivative = derivative < 0 && derivative > -1 ? -1 : derivative > 0 && derivative < 1 ? 1 : derivative; int nextRadius = (one.radius + (derivative * temperature)); //TODO: Metropolis //prevent values larger than the image nextRadius = nextRadius < 0 ? distanceToCenter.width() / 2 - nextRadius : nextRadius; nextRadius = nextRadius % (distanceToCenter.width() / 2); RadiusResult next = getValueForRadius(distanceToCenter, nextRadius); return getRadiusRecursivly(distanceToCenter, next, one, temperature * 0.95); };
void FieldAlgorithms::thresholdGrad(MultiArray<2, float> &basis, MultiArray<2, TinyVector<float, 2>> &target, float threshold) { for (int j = 0; j < basis.size(); j++) { if (basis[j] < threshold) { target[j][0] = 0; target[j][1] = 0; } } };
void phase_correct_3(MultiArray<complex<float>, 3> & a, Agilent::FID &fid) { float ppe = fid.procpar().realValue("ppe"); float ppe2 = fid.procpar().realValue("ppe2"); float lpe = fid.procpar().realValue("lpe"); float lpe2 = fid.procpar().realValue("lpe2"); float ph = -2*M_PI*ppe/lpe; float ph2 = -2*M_PI*ppe2/lpe2; for (int z = 0; z < a.dims()[2]; z++) { const complex<float> fz = polar(1.f, ph2*z); for (int y = 0; y < a.dims()[1]; y++) { const complex<float> fy = polar(1.f, ph*y); for (int x = 0; x < a.dims()[0]; x++) { complex<float> val = a[{x,y,z}]; val = val * fy * fz; a[{x,y,z}] = val; } } } }
void Deformation::drawFunctions(MultiArray<2, int> &distanceToCenter) { std::vector<MultiArray<2,float>> functions = getFit(distanceToCenter); MultiArray<2,float> resEdge(distanceToCenter.shape()); MultiArray<2,float> resValley(distanceToCenter.shape()); MultiArray<2,float> resBoth(distanceToCenter.shape()); for (int i = 0; i<distanceToCenter.width() / 2;i++) { int yEdge = functions[0][i] > distanceToCenter.height() ? distanceToCenter.height() -1 : (distanceToCenter.height() - (functions[0][i] -1)); int yValley = functions[1][i] > distanceToCenter.height() ? distanceToCenter.height() -1 : (distanceToCenter.height() - (functions[1][i] -1)); int yBoth = functions[2][i] > distanceToCenter.height() ? distanceToCenter.height() -1 : (distanceToCenter.height() - (functions[2][i] -1)); resEdge(i, yEdge) = 1; resValley(i, yValley) = 1; resBoth(i, yBoth) = 1; } exportImage(resEdge,"./../images/results/edgeFunction.png"); exportImage(resValley,"./../images/results/valleyFunction.png"); exportImage(resBoth ,"./../images/results/bothFunction.png"); std::cout << "\n expected Radius: "; int rad = argMax(functions[2]); std::cout << rad; functions[2][rad] = 0; rad = argMax(functions[2]); std::cout << "\n next best Radius: "; std::cout << rad; functions[2][rad] = 0; rad = argMax(functions[2]); std::cout << "\n next best Radius: "; std::cout << rad; functions[2][rad] = 0; rad = argMax(functions[2]); std::cout << "\n next best Radius: "; std::cout << rad; functions[2][rad] = 0; rad = argMax(functions[2]); std::cout << "\n"; }
void fft_shift_3(MultiArray<complex<float>, 3> & a) { int x2 = a.dims()[0] / 2; int y2 = a.dims()[1] / 2; int z2 = a.dims()[2] / 2; MultiArray<complex<float>, 3>::Index size_half{x2,y2,z2}; MultiArray<complex<float>, 3>::Index start_1{0,0,0}; MultiArray<complex<float>, 3>::Index start_2{x2,y2,z2}; for (int i = 0; i < 4; i++) { auto local_1 = start_1; auto local_2 = start_2; if (i < 3) { local_1[i] = a.dims()[i] / 2; local_2[i] = 0; } auto octant_1 = a.slice<3>({local_1}, {size_half}); auto octant_2 = a.slice<3>({local_2}, {size_half}); std::swap_ranges(octant_1.begin(), octant_1.end(), octant_2.begin()); } }
MultiArray<uint64,1> calcula_histograma(MultiArray<uint8,2>& in){ //Histograma MultiArray<uint64,1> r(256); //Inicializamos todos los valores a cero r = 0; //Tamaño del MultiArray imageplus::uint64 x=0,y=0; x = in.dims(0); y = in.dims(1); for (uint64 j=0; j < x; ++j) for (uint64 i=0; i < y; ++i) { r[in[j][i]] += 1; } return r; }
Fields FieldAlgorithms::fieldsByGradientPattern(MultiArray<2, float> & image) { //Get Masks for Valley and Peak //not efficient, but can be scaled easly vigra::ImageImportInfo valleyInfo("../images/valleyMask.png"); MultiArray<2, float> valleyArray(valleyInfo.shape()); importImage(valleyInfo, valleyArray); MultiArray<2, float > valleyMask(9,9); resizeImageNoInterpolation(valleyArray, valleyMask); vigra::ImageImportInfo peakInfo("../images/peakMask.png"); MultiArray<2, float> peakArray(peakInfo.shape()); importImage(peakInfo, peakArray); MultiArray<2, float > peakMask(9,9); resizeImageNoInterpolation(peakArray, peakMask); Pyramid pyramid(image); MultiArray<2, float> valleyField(image.shape()); MultiArray<2, float> peakField(image.shape()); //go 3 octaves for (int i = 3; i > 0; i--) { MultiArray<2, float> resized(pyramid.get(i)); MultiArray<2, float> tmpArr = morphologyByGradientPattern(resized, valleyMask); valleyField += pyramid.toOriginalSize(tmpArr); tmpArr = morphologyByGradientPattern(resized, peakMask); peakField += pyramid.toOriginalSize(tmpArr); } //Edge as Gradients MultiArray<2, float> edgeField(image.shape()); gaussianGradientMagnitude(image, edgeField, 1.0); //Localize, smooth for increased range of interaction (following local maxima) MultiArray<2, float> smoothed(valleyField.shape()); gaussianSmoothMultiArray(valleyField, smoothed, 6.0); std::vector<Shape2> valleyLocals(localizePOI(smoothed)); //Result as Field Object Fields fields(valleyField, valleyLocals, peakField, edgeField, image); //A heuristic initialization of the localization, as a priori known position Shape2 nextToIris = Shape2(image.width() / 2 + 10, image.height() / 2); fields.specializedIrisValley = Shape2(image.width() / 2 + 10, image.height() / 2 + 15);//localizeByFollowingLocalMaxima(valleyField, nextToIris); return fields; };
MultiArray<uint8,2> ecualiza_histograma (const MultiArray<float64,2>& in){ //Tamaño del MultiArray uint64 x=0,y=0; x = in.dims(0); y = in.dims(1); //Calculamos el histograma y lo normalizamos MultiArray<uint64,1> histogram; MultiArray<uint8,2> in_conv = convert<uint8>(in); histogram = calcula_histograma(in_conv); //std::cout << histogram << std::endl; //Calculamos la acumulada MultiArray<int64,1> prob(256); prob[0] = histogram[0]; for(int64 i=1; i<256; i++){ prob[i] = histogram[i] + prob[i-1]; } //Imagen resultante MultiArray<uint8,2> result(x,y); int64 min = minval(prob); //std::cout << "Max " << maxval(in) << " Max converted " << int64(maxval(in_conv)) << " Min converted " << int64(minval(in_conv)) << std::endl; for (uint64 j=0; j < x; ++j) for (uint64 i=0; i < y; ++i) { float64 num = (float64)(prob[in_conv[j][i]] - min); float64 den = 1 - min; float64 a = (num/den) * 255.0; if( a > 255.0 ){ a = 255.0; }else if( a < 0.0 ){ a = 0.0; } result[j][i] = mnint<uint8>(a); } return result; }
void fitPSF(DataParams ¶ms, MultiArray<2, double> &ps) { double minval=9999999, maxval = 0; int size = 2*ps.shape(0)*ps.shape(1); std::vector<double> data2(2*ps.shape(0)*ps.shape(1)); for(int i=0, counter = 0;i<ps.shape(0);++i) { for(int j=0;j<ps.shape(1);++j,++counter) { //std::cout<<i<<" "<<j<<" "<<counter<<std::endl; data2[2*counter] = std::sqrt(std::abs(std::pow(i-ps.shape(0)/2,2)+std::pow(j-ps.shape(1)/2,2))); data2[2*counter+1] = ps(i,j); if (ps(i,j)< minval){minval = ps(i,j);} if (ps(i,j)> maxval){maxval = ps(i,j);} } } double sigma = 2.0, scale = maxval - minval, offset = minval; //std::cout<<sigma<<" "<<scale<<" "<<offset<<std::endl; fitGaussian(&data2[0], size/2, sigma, scale, offset); params.setSigma(sigma); }
int main(int argc, char **argv) { int indexptr = 0, c; string outPrefix = ""; bool zip = false, kspace = false, procpar = false; Filters filterType = Filters::None; float f_a = 0, f_q = 0; Nifti::DataType dtype = Nifti::DataType::COMPLEX64; Affine3f scale; scale = Scaling(1.f); while ((c = getopt_long(argc, argv, short_options, long_options, &indexptr)) != -1) { switch (c) { case 0: break; // It was an option that just sets a flag. case 'o': outPrefix = string(optarg); break; case 'z': zip = true; break; case 'k': kspace = true; break; case 'm': dtype = Nifti::DataType::FLOAT32; break; case 's': scale = Scaling(static_cast<float>(atof(optarg))); break; case 'f': switch (*optarg) { case 'h': filterType = Filters::Hanning; f_a = 0.1; break; case 't': filterType = Filters::Tukey; f_a = 0.75; f_q = 0.25; break; default: cerr << "Unknown filter type: " << string(optarg, 1) << endl; return EXIT_FAILURE; } break; case 'a': if (filterType == Filters::None) { cerr << "No filter type specified, so f_a is invalid" << endl; return EXIT_FAILURE; } f_a = atof(optarg); break; case 'q': if (filterType != Filters::Tukey) { cerr << "Filter type is not Tukey, f_q is invalid" << endl; return EXIT_FAILURE; } f_q = atof(optarg); break; case 'p': procpar = true; break; case 'v': verbose = true; break; case '?': // getopt will print an error message cout << usage << endl; return EXIT_FAILURE; default: cout << "Unhandled option " << string(1, c) << endl; return EXIT_FAILURE; } } if ((argc - optind) <= 0) { cout << usage << endl; cout << "No .fids specified" << endl; return EXIT_FAILURE; } while (optind < argc) { string inPath(argv[optind++]); size_t fileSep = inPath.find_last_of("/") + 1; size_t fileExt = inPath.find_last_of("."); if ((fileExt == string::npos) || (inPath.substr(fileExt) != ".fid")) { cerr << inPath << " is not a valid .fid directory" << endl; } string outPath = outPrefix + inPath.substr(fileSep, fileExt - fileSep) + ".nii"; if (zip) outPath = outPath + ".gz"; Agilent::FID fid(inPath); string apptype = fid.procpar().stringValue("apptype"); string seqfil = fid.procpar().stringValue("seqfil"); if (apptype != "im3D") { cerr << "apptype " << apptype << " not supported, skipping." << endl; continue; } if (verbose) { cout << fid.print_info() << endl; cout << "apptype = " << apptype << endl; cout << "seqfil = " << seqfil << endl; } /* * Assemble k-Space */ MultiArray<complex<float>, 4> vols; if (seqfil.substr(0, 5) == "mge3d") { vols = reconMGE(fid); } else if (seqfil.substr(0, 7) == "mp3rage") { vols = reconMP2RAGE(fid); } else { cerr << "Recon for " << seqfil << " not implemented, skipping." << endl; continue; } /* * Build and apply filter */ MultiArray<float, 3> filter; switch (filterType) { case Filters::None: break; case Filters::Hanning: if (verbose) cout << "Building Hanning filter" << endl; filter = Hanning3D(vols.dims().head(3), f_a); break; case Filters::Tukey: if (verbose) cout << "Building Tukey filter" << endl; filter = Tukey3D(vols.dims().head(3), f_a, f_q); break; } if (filterType != Filters::None) { if (verbose) cout << "Applying filter" << endl; for (int v = 0; v < vols.dims()[3]; v++) { MultiArray<complex<float>, 3> vol = vols.slice<3>({0,0,0,v},{-1,-1,-1,0}); ApplyFilter3D(vol,filter); } } /* * FFT */ if (!kspace) { for (int v = 0; v < vols.dims()[3]; v++) { if (verbose) cout << "FFTing vol " << v << endl; MultiArray<complex<float>, 3> vol = vols.slice<3>({0,0,0,v},{-1,-1,-1,0}); phase_correct_3(vol, fid); fft_shift_3(vol); fft_X(vol); fft_Y(vol); fft_Z(vol); fft_shift_3(vol); } } if (verbose) cout << "Writing file: " << outPath << endl; list<Nifti::Extension> exts; if (procpar) { if (verbose) cout << "Embedding procpar" << endl; ifstream pp_file(inPath + "/procpar", ios::binary); pp_file.seekg(ios::end); size_t fileSize = pp_file.tellg(); pp_file.seekg(ios::beg); vector<char> data; data.reserve(fileSize); data.assign(istreambuf_iterator<char>(pp_file), istreambuf_iterator<char>()); exts.emplace_back(NIFTI_ECODE_COMMENT, data); } Affine3f xform = scale * fid.procpar().calcTransform(); ArrayXf voxdims = (Affine3f(xform.rotation()).inverse() * xform).matrix().diagonal(); Nifti::Header outHdr(vols.dims(), voxdims, dtype); outHdr.setTransform(xform); Nifti::File output(outHdr, outPath, exts); output.writeVolumes(vols.begin(), vols.end(), 0, vols.dims()[3]); output.close(); } return 0; }
double fitPSF2D(MultiArray<2, double> &ps, double &sigma) { double minval=9999999, maxval = 0; int w = ps.shape(0), h = ps.shape(1); int size = ps.shape(0)*ps.shape(1); std::vector<double> data2(3*ps.shape(0)*ps.shape(1)); //std::ofstream outputRoi; //outputRoi.open("c:\\tmp\\outputRoi.txt"); for(int i=0, counter = 0;i<ps.shape(0);++i) { for(int j=0;j<ps.shape(1);++j,++counter) { //std::cout<<i<<" "<<j<<" "<<counter<<std::endl; // outputRoi <<i<<" "<<j<<" "<<ps(i,j)<<std::endl; data2[3*counter] = i-ps.shape(0)/2; data2[3*counter+1] = j-ps.shape(1)/2; data2[3*counter+2] = ps(i,j); if (ps(i,j)< minval){minval = ps(i,j);} if (ps(i,j)> maxval){maxval = ps(i,j);} } } //outputRoi.close(); double scale = maxval - minval, offset = minval, x0=0, y0=0; sigma = 2.0; //std::cout<<"sigma: "<<sigma<<" scale: "<<scale<<" offset:"<<offset<<std::endl; fitGaussian2D(&data2[0], size, sigma, scale, offset, x0, y0); double SSE = 0, SSD = 0, sumY = 0, sumY2 = 0; for(int i= w/2-2, counter = 0;i<w/2+2;++i) { for(int j=h/2-2;j<h/2+2;++j,++counter) { double xs = sq((i-ps.shape(0)/2 - x0) / sigma)+ sq((j-ps.shape(1)/2 - y0) / sigma); double e = std::exp(-0.5 * xs); double r = ps(i,j) - (scale * e + offset); SSE += r*r; sumY+= ps(i,j); sumY2+= sq(ps(i,j)); } } SSD = sumY2 - sq(sumY) / size; double error = 1-SSE/SSD; sigma = std::abs(sigma); //std::cout<<"sigma: "<<sigma<<" scale: "<<scale<<" offset:"<<offset<< " x0: " << x0<<" y0: "<<y0<<" Error: "<<error<<std::endl; //std::cin.get(); return error; }