CARTAvis / carta-backend

Source code repository for the backend component of CARTA, a new visualization tool designed for the ALMA, the VLA and the SKA pathfinders.
https://cartavis.github.io/
GNU General Public License v3.0
22 stars 11 forks source link

Check whether the FITS beam table consists of 64-bit floats #1273

Closed markccchiang closed 1 year ago

markccchiang commented 1 year ago

Description

Checklist

pford commented 1 year ago

CartaFitsImage::ReadBeamsTable reads these columns as TFLOAT. Shouldn't this be fixed as well, to determine the column type then read the values as TFLOAT or TDOUBLE? casacore::Quantity expects a double value with a string unit so that is no problem.

markccchiang commented 1 year ago

CartaFitsImage::ReadBeamsTable reads these columns as TFLOAT. Shouldn't this be fixed as well, to determine the column type then read the values as TFLOAT or TDOUBLE? casacore::Quantity expects a double value with a string unit so that is no problem.

It seems in function fits_read_col if the reading data type is inconsistent with the writing data type of an array we declared, an error or crash would happen. So maybe it is ok to keep the original way that we convert all beam parameters to the float type(?)

pford commented 1 year ago

CartaFitsImage::ReadBeamsTable reads these columns as TFLOAT. Shouldn't this be fixed as well, to determine the column type then read the values as TFLOAT or TDOUBLE? casacore::Quantity expects a double value with a string unit so that is no problem.

It seems in function fits_read_col if the reading data type is inconsistent with the writing data type of an array we declared, an error or crash would happen. So maybe it is ok to keep the original way that we convert all beam parameters to the float type(?)

I am suggesting that we determine the column datatype (fits_get_coltype) then read the data as that type, rather than losing precision converting double to float and back to double.

// for bmaj
std::string bmaj_name("BMAJ");
fits_get_colnum(fptr, casesen, bmaj_name.c_str(), &colnum, &status);
fits_get_coltype(fptr, colnum, &datatype, &repeat, &width, &status);

std::vector<float> bmaj_f;
std::vector<double> bmaj_d;

if (datatype == TFLOAT) {
    bmaj_f.resize(nrow);
    fits_read_col(fptr, datatype, colnum, firstrow, firstelem, nrow, fnulval, bmaj_f.data(), &anynul, &status);
} else if (datatype == TDOUBLE) {
    bmaj_d.resize(nrow);
    fits_read_col(fptr, datatype, colnum, firstrow, firstelem, nrow, fnulval, bmaj_d.data(), &anynul, &status);
}

Better to put this in a method, something like GetColumnData(fitsfile* fptr, const std::string& name, int nrow, int& datatype, std::vector<float>& values_f, std::vector<double>& values_d) where the returned datatype tells you which returned vector to use to set the Quantities (or do not return datatype and just check which vector is not empty). Then call the method for "BMAJ", "BMIN", "BPA".

markccchiang commented 1 year ago

Better to put this in a method, something like GetColumnData(fitsfile* fptr, const std::string& name, int nrow, int& datatype, std::vector<float>& values_f, std::vector<double>& values_d) where the returned datatype tells you which returned vector to use to set the Quantities (or do not return datatype and just check which vector is not empty). Then call the method for "BMAJ", "BMIN", "BPA".

Thank you for the suggestion! I refactored this part of the code in a slightly different way, added a check for the data type, and got a data array accordingly. Hope it is easier to read.

github-actions[bot] commented 1 year ago

Code Coverage

Package Line Rate Health
src.Cache 66%
src.DataStream 52%
src.FileList 67%
src.Frame 50%
src.HttpServer 43%
src.ImageData 28%
src.ImageFitter 89%
src.ImageGenerators 44%
src.ImageStats 76%
src.Logger 44%
src.Main 54%
src.Region 18%
src.Session 29%
src.Table 52%
src.ThreadingManager 87%
src.Timer 85%
src.Util 49%
Summary 38% (6965 / 18364)