Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mark/1178 supports loading swapped-axes image cubes #1194

Merged
merged 53 commits into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
aa340bc
Do not fix the render axes to direction axes
markccchiang Sep 8, 2022
bcebbc3
Modify the changelog
markccchiang Sep 8, 2022
fcf9c33
Add axes numbers for Ra, Dec, Spectral and Stokes in the file info
markccchiang Sep 10, 2022
70a10bf
Add axes numbers in the file info extended message
markccchiang Sep 10, 2022
a6c5dc1
A minor code change
markccchiang Sep 12, 2022
d212cbb
Fix the problem of showing PV image coordinates for swapped axes cubes
markccchiang Sep 12, 2022
c6d382d
Identify key words GLON or GLAT as direction axes
markccchiang Sep 13, 2022
97798ef
Remove unused codes
markccchiang Sep 13, 2022
fa79f05
Modify the protobuf message AxesNumbers
markccchiang Sep 13, 2022
c431952
Change axis indices from 0-based to 1-based in the axes_numbers message
markccchiang Oct 3, 2022
c14c257
Minor code changes and refactoring
markccchiang Oct 3, 2022
09f229e
Fix an unit test error for the file info
markccchiang Oct 3, 2022
88d2037
Revert coordinate settings in PV generator
markccchiang Oct 4, 2022
da2949c
Solve a merge conflict in changelog
markccchiang Oct 4, 2022
91d4ef9
Refactor codes
markccchiang Oct 4, 2022
0a4f763
Merge branch 'dev' of https://github.com/CARTAvis/carta-backend into …
markccchiang Nov 14, 2022
1f72ab2
Update the protobuf submodule
markccchiang Nov 21, 2022
f0fac19
Solve merge conflicts
markccchiang Nov 21, 2022
6c36e34
Solve a merge conflict in changelog
markccchiang Nov 28, 2022
671024d
Merge branch 'dev' of https://github.com/CARTAvis/carta-backend into …
markccchiang Nov 29, 2022
8e65f58
Minor code changes
markccchiang Nov 29, 2022
905eded
Fix the problem of loading image file if it has both linear and direc…
markccchiang Nov 30, 2022
df993e4
Fix the error of showing direction axes range names in the file info …
markccchiang Nov 30, 2022
8e39ce0
Modify file info on the file browser for swapped image cubes
markccchiang Nov 30, 2022
732c824
Fix the problem of showing direction axis names for compressed images
markccchiang Nov 30, 2022
51feea8
Update the protobuf with the new dev branch
markccchiang Dec 2, 2022
c5c1cc7
Solve merge conflicts
markccchiang Dec 2, 2022
a7a37c0
Change the name of linear axis for a PV image as OFFSET
markccchiang Dec 2, 2022
511bdfd
Fix the name of non-direction axis for axis number is 0 or 1
markccchiang Dec 6, 2022
a9c4f04
Remove the function GetRenderAxes from the FileLoader
markccchiang Dec 6, 2022
0c59ee0
Fix the problem of axis names displayed on the file info panel
markccchiang Dec 15, 2022
6f2afc6
Merge branch 'dev' of https://github.com/CARTAvis/carta-backend into …
markccchiang Dec 26, 2022
3d9afd3
Fix the problem of an image without direction axes info for AST rende…
markccchiang Jan 4, 2023
9380630
Update the protobuf submodule with the new dev branch
markccchiang Jan 10, 2023
57daf49
Merge branch 'dev' of https://github.com/CARTAvis/carta-backend into …
markccchiang Jan 10, 2023
e10be2f
Update the protobuf and modify the changelog and the index
markccchiang Jan 10, 2023
b81fbf7
Get axes names through the image loader or the header entries
markccchiang Jan 12, 2023
f8d44fc
Correct the definition of number of channels is spectral axis size
markccchiang Jan 12, 2023
3828815
Solve a merge conflict in changelog
markccchiang Jan 12, 2023
732b788
Solve a merge conflict in the changlog
markccchiang Feb 2, 2023
55d6f75
Skip the stokes axis when rendering an image
markccchiang Feb 22, 2023
77a33ff
Get axis names from header entries that shown on the file info panel
markccchiang Feb 22, 2023
91e1c58
Modify the file info tester
markccchiang Feb 22, 2023
793a2b6
Represent the longitudinal coordinate value in the rangge [0, 360] deg
markccchiang Feb 26, 2023
a9463a4
Correct the syntax to initialize values for axis names
markccchiang Feb 28, 2023
36868ea
Fix the reversed PV generation when getting with fixed angular region…
markccchiang Mar 2, 2023
3fe5529
Merge branch 'dev' of https://github.com/CARTAvis/carta-backend into …
markccchiang Mar 13, 2023
3a3085a
Rename variables for directional axes as spatial axes
markccchiang Mar 13, 2023
b1e7177
Update the protobuf messages for spatial axes
markccchiang Mar 14, 2023
a01fe00
Fix the reference Dec value shown on the file info panel
markccchiang Mar 14, 2023
341e799
Minor code changes
markccchiang Mar 15, 2023
c446d83
bumped protobuf commit
confluence Mar 22, 2023
62b2c48
Merge branch 'mark/1178_set_render_axes_as_0_and_1' of github.com:CAR…
confluence Mar 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added support to keep previously generated moment images ([#1202](https://github.com/CARTAvis/carta-backend/issues/1202)).
* Added pugixml as a third-party library with the option PUGIXML_COMPACT enabled ([#1217](https://github.com/CARTAvis/carta-backend/issues/1217)).
* Added automatically generated documentation with Doxygen ([#1215](https://github.com/CARTAvis/carta-backend/issues/1215)).
* Added support for loading swapped-axes image cubes ([#1178](https://github.com/CARTAvis/carta-backend/issues/1178)).

### Changed
* Removed CASA CRTF parser for performance and annotation region support ([#1219](https://github.com/CARTAvis/carta-backend/issues/1219)).
Expand Down
2 changes: 1 addition & 1 deletion carta-protobuf
172 changes: 120 additions & 52 deletions src/FileList/FileExtInfoLoader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,15 @@ bool FileExtInfoLoader::FillFileInfoFromImage(CARTA::FileInfoExtended& extended_

AddDataTypeEntry(extended_info, data_type);

int spectral_axis, depth_axis, stokes_axis;
if (_loader->FindCoordinateAxes(image_shape, spectral_axis, depth_axis, stokes_axis, message)) {
std::vector<int> direction_axes, render_axes;
int spectral_axis, stokes_axis, depth_axis;
if (_loader->FindCoordinateAxes(
image_shape, direction_axes, spectral_axis, stokes_axis, render_axes, depth_axis, message)) {
casacore::Vector<casacore::String> axes_names;
AddShapeEntries(
extended_info, image_shape, direction_axes, spectral_axis, stokes_axis, render_axes, depth_axis, axes_names);

// Computed entries for rendered image axes, depth axis (may not be spectral), stokes axis
std::vector<int> render_axes = _loader->GetRenderAxes();
AddShapeEntries(extended_info, image_shape, spectral_axis, depth_axis, stokes_axis, render_axes);
AddComputedEntries(extended_info, image.get(), render_axes, use_image_for_entries);
info_ok = true;
}
Expand Down Expand Up @@ -593,8 +597,10 @@ void FileExtInfoLoader::AddInitialComputedEntries(const std::string& hdu, CARTA:

// Use header entries to determine computed entries
casacore::IPosition shape;
int chan_axis(-1), depth_axis(-1), stokes_axis(-1);
std::vector<std::string> spectral_ctypes = {"ENER", "VOPT", "ZOPT", "VELO", "VRAD", "BETA"};
std::vector<int> direction_axes(2, -1);
int spectral_axis(-1), stokes_axis(-1), depth_axis(-1);
casacore::Vector<casacore::String> axes_names(4, "NA");
std::vector<std::string> spectral_ctypes = {"FREQ", "WAV", "ENER", "VOPT", "ZOPT", "VELO", "VRAD", "BETA", "FELO"};
casacore::DataType data_type(casacore::DataType::TpFloat);

for (int i = 0; i < extended_info.header_entries_size(); ++i) {
Expand All @@ -620,17 +626,34 @@ void FileExtInfoLoader::AddInitialComputedEntries(const std::string& hdu, CARTA:
std::string ctype_index(&entry_name.back());
int axis_num = stoi(ctype_index) - 1;
auto entry_value = header_entry.value();
std::transform(entry_value.begin(), entry_value.end(), entry_value.begin(), [](unsigned char c) { return std::toupper(c); });

if (entry_value == "STOKES") {
stokes_axis = axis_num;
} else if ((entry_value.find("FREQ") == 0) || (entry_value.find("WAV") != std::string::npos) ||
(std::find(spectral_ctypes.begin(), spectral_ctypes.end(), entry_value) != spectral_ctypes.end())) {
chan_axis = axis_num;
if (chan_axis > 1) {
depth_axis = chan_axis;

if (!entry_value.empty()) {
entry_value = entry_value.substr(0, entry_value.find("-", 0));
std::transform(
entry_value.begin(), entry_value.end(), entry_value.begin(), [](unsigned char c) { return std::toupper(c); });

// Fill in axis names
if (axis_num >= 0 && axis_num < axes_names.size()) {
axes_names[axis_num] = entry_value;
}

// Assign axis numbers for different types
if (entry_value.find("RA") == 0 || entry_value.find("GLON") == 0 || entry_value.find("UU") == 0) {
direction_axes[0] = axis_num;
} else if (entry_value.find("DEC") == 0 || entry_value.find("GLAT") == 0 || entry_value.find("VV") == 0) {
direction_axes[1] = axis_num;
} else if (entry_value.find("STOKES") == 0) {
stokes_axis = axis_num;
} else if (std::any_of(spectral_ctypes.begin(), spectral_ctypes.end(),
[&](const std::string& key_word) { return (entry_value.find(key_word) != std::string::npos); })) {
spectral_axis = axis_num;
}
}

// Depth axis is not the first two axes [0, 1], i.e., non-render axis that is not stokes (if any)
if (axis_num > 1 && axis_num != stokes_axis) {
depth_axis = axis_num;
}
} else if (entry_name.find("BITPIX") == 0) {
auto value = header_entry.value();
std::unordered_map<std::string, casacore::DataType> bitpix_types(
Expand All @@ -643,7 +666,7 @@ void FileExtInfoLoader::AddInitialComputedEntries(const std::string& hdu, CARTA:
}

AddDataTypeEntry(extended_info, data_type);
AddShapeEntries(extended_info, shape, chan_axis, depth_axis, stokes_axis, render_axes);
AddShapeEntries(extended_info, shape, direction_axes, spectral_axis, stokes_axis, render_axes, depth_axis, axes_names);

if (compressed_fits) {
compressed_fits->SetShape(shape);
Expand All @@ -665,13 +688,15 @@ void FileExtInfoLoader::AddDataTypeEntry(CARTA::FileInfoExtended& extended_info,
entry->set_entry_type(CARTA::EntryType::STRING);
}

void FileExtInfoLoader::AddShapeEntries(CARTA::FileInfoExtended& extended_info, const casacore::IPosition& shape, int chan_axis,
int depth_axis, int stokes_axis, const std::vector<int>& render_axes) {
void FileExtInfoLoader::AddShapeEntries(CARTA::FileInfoExtended& extended_info, const casacore::IPosition& shape,
const std::vector<int>& direction_axes, int spectral_axis, int stokes_axis, const std::vector<int>& render_axes, int depth_axis,
casacore::Vector<casacore::String>& axes_names) {
// Set fields/header entries for shape: dimensions, width, height, depth, stokes
int num_dims(shape.size());
int width(shape(render_axes[0]));
int height(shape(render_axes[1]));
int depth(depth_axis >= 0 ? shape(depth_axis) : 1);
int channels(spectral_axis >= 0 ? shape(spectral_axis) : 1);
int stokes(stokes_axis >= 0 ? shape(stokes_axis) : 1);

extended_info.set_dimensions(num_dims);
Expand All @@ -680,41 +705,78 @@ void FileExtInfoLoader::AddShapeEntries(CARTA::FileInfoExtended& extended_info,
extended_info.set_depth(depth);
extended_info.set_stokes(stokes);

auto* axes_numbers_info = extended_info.mutable_axes_numbers();
// Change to 1-based axis indices
axes_numbers_info->set_dir_x(direction_axes[0] + 1);
axes_numbers_info->set_dir_y(direction_axes[1] + 1);
axes_numbers_info->set_spectral(spectral_axis + 1);
axes_numbers_info->set_stokes(stokes_axis + 1);
axes_numbers_info->set_depth(depth_axis + 1);

if (axes_names.empty()) {
// Set axis names with respect to axis numbers 1~4
axes_names.assign(casacore::Vector<casacore::String>(4, "NA"));
for (int i = 0; i < extended_info.header_entries_size(); ++i) {
auto header_entry = extended_info.header_entries(i);
auto entry_name = header_entry.name();
if (entry_name.find("CTYPE") == 0) {
auto entry_value = header_entry.value();
if (!entry_value.empty()) {
entry_value = entry_value.substr(0, entry_value.find("-", 0));
if (entry_name.back() == '1') {
axes_names[0] = entry_value;
} else if (entry_name.back() == '2') {
axes_names[1] = entry_value;
} else if (entry_name.back() == '3') {
axes_names[2] = entry_value;
} else if (entry_name.back() == '4') {
axes_names[3] = entry_value;
}
}
}
}
}

// In case if the stokes axis name is not available from the header info
if (stokes_axis > -1 && axes_names[stokes_axis] == "NA") {
axes_names[stokes_axis] = "STOKES";
}

// shape computed_entry
std::string shape_string;
switch (num_dims) {
case 2:
shape_string = fmt::format("[{}, {}]", shape(0), shape(1));
shape_string = fmt::format("[{}, {}] ({}, {})", shape(0), shape(1), axes_names[0], axes_names[1]);
break;
case 3:
shape_string = fmt::format("[{}, {}, {}]", shape(0), shape(1), shape(2));
shape_string =
fmt::format("[{}, {}, {}] ({}, {}, {})", shape(0), shape(1), shape(2), axes_names[0], axes_names[1], axes_names[2]);
break;
case 4:
shape_string = fmt::format("[{}, {}, {}, {}]", shape(0), shape(1), shape(2), shape(3));
shape_string = fmt::format("[{}, {}, {}, {}] ({}, {}, {}, {})", shape(0), shape(1), shape(2), shape(3), axes_names[0],
axes_names[1], axes_names[2], axes_names[3]);
break;
}
auto shape_entry = extended_info.add_computed_entries();
shape_entry->set_name("Shape");
shape_entry->set_value(shape_string);
shape_entry->set_entry_type(CARTA::EntryType::STRING);

if (chan_axis >= 0) {
if (spectral_axis >= 0) {
// header entry for number of channels
unsigned int nchan = shape(chan_axis);
auto entry = extended_info.add_computed_entries();
entry->set_name("Number of channels");
entry->set_value(std::to_string(nchan));
entry->set_value(std::to_string(channels));
entry->set_entry_type(CARTA::EntryType::INT);
entry->set_numeric_value(nchan);
entry->set_numeric_value(channels);
}
if (stokes_axis >= 0) {
// header entry for number of stokes
unsigned int nstokes = shape(stokes_axis);
auto entry = extended_info.add_computed_entries();
entry->set_name("Number of polarizations");
entry->set_value(std::to_string(nstokes));
entry->set_value(std::to_string(stokes));
entry->set_entry_type(CARTA::EntryType::INT);
entry->set_numeric_value(nstokes);
entry->set_numeric_value(stokes);
}
}

Expand Down Expand Up @@ -781,8 +843,8 @@ void FileExtInfoLoader::AddComputedEntries(CARTA::FileInfoExtended& extended_inf
entry->set_value(format_coords);
entry->set_entry_type(CARTA::EntryType::STRING);

bool coord0IsDir(coord0.isConform("deg")), coord1IsDir(coord1.isConform("deg"));
if (coord0IsDir || coord1IsDir) {
bool is_coord0_dir(coord0.isConform("deg")), is_coord1_dir(coord1.isConform("deg"));
if (is_coord0_dir || is_coord1_dir) {
// Reference coord(s) converted to deg
std::string ref_coords_deg = ConvertCoordsToDeg(coord0, coord1);
// Add ref coords in deg
Expand Down Expand Up @@ -1243,19 +1305,22 @@ std::string FileExtInfoLoader::MakeAngleString(const std::string& type, double v
return fmt::format("{:.6g} {}", val, unit);
}

casacore::Quantity quant1(val, unit);
casacore::Quantity quant1(val, unit), pi2(360, "deg");
if (format == casacore::MVAngle::ANGLE && quant1.get("deg").getValue() < 0) {
quant1 += pi2;
}
casacore::MVAngle mva(quant1);
return mva.string(format, 10);
}

std::string FileExtInfoLoader::ConvertCoordsToDeg(const casacore::Quantity& coord0, const casacore::Quantity& coord1) {
// If possible, convert quantities to degrees. Return formatted string
casacore::Quantity coord0_deg(coord0), coord1_deg(coord1);
casacore::Quantity coord0_deg(coord0), coord1_deg(coord1), pi2(360, "deg");
if (coord0.isConform("deg")) {
coord0_deg = coord0.get("deg");
coord0_deg = coord0.get("deg").getValue() < 0 ? (coord0 + pi2).get("deg") : coord0.get("deg");
}
if (coord1.isConform("deg")) {
coord1_deg = coord1.get("deg");
coord1_deg = coord1.get("deg").getValue() < 0 ? (coord1 + pi2).get("deg") : coord1.get("deg");
}

return fmt::format("[{}, {}]", coord0_deg, coord1_deg);
Expand Down Expand Up @@ -1373,26 +1438,29 @@ void FileExtInfoLoader::AddCoordRanges(
std::string y_end = direction_coord.format(units, casacore::Coordinate::DEFAULT, y_max, 1, true, true);

// Set x and y coordinate names
if (axis_names(0) == "Right Ascension") {
axis_names(0) = "RA";
} else if (axis_names(0) == "Longitude") {
axis_names(0) = "LON";
}
if (axis_names(1) == "Declination") {
axis_names(1) = "DEC";
} else if (axis_names(1) == "Latitude") {
axis_names(1) = "LAT";
if (direction_axes[0] > -1 && direction_axes[0] < axis_names.size()) {
if (axis_names(direction_axes[0]) == "Right Ascension") {
axis_names(direction_axes[0]) = "RA";
} else if (axis_names(direction_axes[0]) == "Longitude") {
axis_names(direction_axes[0]) = "LON";
}
auto* x_entry = extended_info.add_computed_entries();
x_entry->set_name(fmt::format("{} range", axis_names(direction_axes[0])));
x_entry->set_value(fmt::format("[{}, {}]", x_start, x_end));
x_entry->set_entry_type(CARTA::EntryType::STRING);
}

auto* x_entry = extended_info.add_computed_entries();
x_entry->set_name(fmt::format("{} range", axis_names(0)));
x_entry->set_value(fmt::format("[{}, {}]", x_start, x_end));
x_entry->set_entry_type(CARTA::EntryType::STRING);

auto* y_entry = extended_info.add_computed_entries();
y_entry->set_name(fmt::format("{} range", axis_names(1)));
y_entry->set_value(fmt::format("[{}, {}]", y_start, y_end));
y_entry->set_entry_type(CARTA::EntryType::STRING);
if (direction_axes[1] > -1 && direction_axes[1] < axis_names.size()) {
if (axis_names(direction_axes[1]) == "Declination") {
axis_names(direction_axes[1]) = "DEC";
} else if (axis_names(direction_axes[1]) == "Latitude") {
axis_names(direction_axes[1]) = "LAT";
}
auto* y_entry = extended_info.add_computed_entries();
y_entry->set_name(fmt::format("{} range", axis_names(direction_axes[1])));
y_entry->set_value(fmt::format("[{}, {}]", y_start, y_end));
y_entry->set_entry_type(CARTA::EntryType::STRING);
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/FileList/FileExtInfoLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ class FileExtInfoLoader {

// Computed entries
void AddDataTypeEntry(CARTA::FileInfoExtended& extended_info, casacore::DataType data_type);
void AddShapeEntries(CARTA::FileInfoExtended& extended_info, const casacore::IPosition& shape, int chan_axis, int depth_axis,
int stokes_axis, const std::vector<int>& render_axes);
void AddShapeEntries(CARTA::FileInfoExtended& extended_info, const casacore::IPosition& shape, const std::vector<int>& direction_axes,
int spectral_axis, int stokes_axis, const std::vector<int>& render_axes, int depth_axis,
casacore::Vector<casacore::String>& axes_names);
void AddInitialComputedEntries(const std::string& hdu, CARTA::FileInfoExtended& extended_info, const std::string& filename,
const std::vector<int>& render_axes, CompressedFits* compressed_fits = nullptr);
void AddComputedEntries(CARTA::FileInfoExtended& extended_info, casacore::ImageInterface<float>* image,
Expand Down
6 changes: 2 additions & 4 deletions src/Frame/Frame.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,16 @@ Frame::Frame(uint32_t session_id, std::shared_ptr<FileLoader> loader, const std:

// Get shape and axis values from the loader
std::string log_message;
if (!_loader->FindCoordinateAxes(_image_shape, _spectral_axis, _z_axis, _stokes_axis, log_message)) {
std::vector<int> direction_axes, render_axes;
if (!_loader->FindCoordinateAxes(_image_shape, direction_axes, _spectral_axis, _stokes_axis, render_axes, _z_axis, log_message)) {
_open_image_error = fmt::format("Cannot determine file shape. {}", log_message);
spdlog::error("Session {}: {}", session_id, _open_image_error);
_valid = false;
return;
}

// Determine which axes are rendered, e.g. for pV images
std::vector<int> render_axes = _loader->GetRenderAxes();
_x_axis = render_axes[0];
_y_axis = render_axes[1];

_width = _image_shape(_x_axis);
_height = _image_shape(_y_axis);
_depth = (_z_axis >= 0 ? _image_shape(_z_axis) : 1);
Expand Down
3 changes: 2 additions & 1 deletion src/Frame/Frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,8 @@ class Frame {

// Shape and axis info: X, Y, Z, Stokes
casacore::IPosition _image_shape;
int _x_axis, _y_axis, _z_axis, _spectral_axis, _stokes_axis;
int _x_axis, _y_axis, _z_axis; // X and Y are render axes, Z is depth axis (non-render axis) that is not stokes (if any)
int _spectral_axis, _stokes_axis;
int _z_index, _stokes_index; // current index
size_t _width, _height, _depth, _num_stokes;

Expand Down
Loading