[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master 68823e3 17/19: Library (fits.h): correctly rea
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master 68823e3 17/19: Library (fits.h): correctly reading columns of 0 width/repeat |
Date: |
Sun, 14 Nov 2021 20:41:01 -0500 (EST) |
branch: master
commit 68823e3fcdda63eac27d05f7cb0f399dfeeff2da
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Library (fits.h): correctly reading columns of 0 width/repeat
Until now, if a column of a FITS binary table had a 0 width or "repeat"
value (in the TFORM keyword, for example '0A' in for a 0-repeat string
column), Gnuastro would crash with the following CFITSIO error:
FITSIO status = 308: bad first element number
First element to write is too large: 1; max allowed value is 0
This was because until now, we were assuming that a column always has
atleast one element!
With this commit, upon reading the table's metadata (and discovering that
it has a "repeat" value of 0), a bit flag is set so when we actually want
to read the column, in such cases, it will simply read an all-blank set of
values (which would be the equivalent value in Gnuastro's internal data
structure, for now).
In the process the following changes are also made:
- Until now, there was only a single column metadata flag, so we had used
an 'enum' and '==' to check for it. But with this commit, we need more
than one flag, so the flags are now bit flags and all relevant checks
have been corrected.
- This whole process happened while I was editing the Matching part of the
Gnuastro book, so those edits are also being committed (they are just
minor copy-edits, and not worth a separate commit!).
---
NEWS | 4 +-
bin/match/ui.c | 2 +
doc/gnuastro.texi | 62 ++++++++++----------
lib/blank.c | 17 +++++-
lib/fits.c | 113 ++++++++++++++++++++++--------------
lib/gnuastro-internal/tableintern.h | 17 ++++--
lib/table.c | 38 ++++++++----
lib/tableintern.c | 2 +-
lib/txt.c | 5 +-
9 files changed, 167 insertions(+), 93 deletions(-)
diff --git a/NEWS b/NEWS
index 89681c1..3df4fcd 100644
--- a/NEWS
+++ b/NEWS
@@ -38,10 +38,12 @@ See the end of the file for license conditions.
and was raised by Sepideh Eskandarlou.
Library:
-
- gal_fits_tab_read: now takes the number of threads (only relevant for
reading FITS tables).
- gal_table_read: simlar to 'gal_fits_tab_read'.
+ - gal_blank_initialize: also works on string data, but initializing only
+ a tile over a larger block of elements is only supported for numeric
+ data types.
** Bugs fixed
bug #61329: make check crash in macOS in convolve/spectrum-1d.sh, found
diff --git a/bin/match/ui.c b/bin/match/ui.c
index 0aefc96..51ef3e2 100644
--- a/bin/match/ui.c
+++ b/bin/match/ui.c
@@ -1272,8 +1272,10 @@ ui_free_report(struct matchparams *p, struct timeval *t1)
gal_data_free(p->outcols);
gal_list_data_free(p->cols1);
gal_list_data_free(p->cols2);
+ if(p->kdtree) free(p->kdtree);
gal_list_str_free(p->acols, 0);
gal_list_str_free(p->bcols, 0);
+ if(p->kdtreehdu) free(p->kdtreehdu);
gal_list_str_free(p->stdinlines, 1);
/* Print the final message. */
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index bf670da..d6dfe28 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -19961,12 +19961,12 @@ The aperture can be a circle or an ellipse with any
orientation.
Matching involves two catalogs, let's call them catalog A (with N rows) and
catalog B (with M rows).
The most basic algorithm that immediately comes to mind is this:
-for each row in A (let's call it @mymath{A_i}), go over all the rows in B and
calculate the distance to each and find the @mymath{B_j} that is nearest to
@mymath{A_i}.
-If the distance between @mymath{A_i} and @mymath{B_j} is below a certain
acceptable threshold (or radius), consider them as a match.
+for each row in A (let's call it @mymath{A_i}), go over all the rows in B
(@mymath{B_j}, where @mymath{0<j<M}) and calculate the distance
@mymath{|B_j-A_i|}.
+If this distance is less than a certain acceptable distance threshold (or
radius), consider @mymath{A_i} and @mymath{B_j} as a match.
-You may think of this (initially genius!) solution: During the parsing, when I
find that @mymath{A_i} and @mymath{B_j} satisfy the match above, I will remove
@mymath{B_j} from the search of matches for @mymath{A_k} (where @mymath{k> i}).
-As a result, as I go down A and more matches are found, I have to calculate
less distances (there are fewer elements in B that remain to be checked).
-However, this will introduce an important bias: @mymath{B_j} may actually be
closer to @mymath{A_k}!
+During the parsing, once you have found that @mymath{A_i} and @mymath{B_j}
satisfy the match above, you can even remove @mymath{B_j} from the search of
matches for @mymath{A_k} (where @mymath{k>i}).
+Therefore, as you go down A (and more matches are found), you have to
calculate less distances (there are fewer elements in B that remain to bex
checked).
+However, this will introduce an important bias: @mymath{B_j} may actually be
closer to @mymath{A_k} than to the matched @mymath{A_i}!
But because @mymath{A_i} happened to be before @mymath{A_k} in your table, you
removed @mymath{B_j} from the potential search domain of @mymath{A_k}.
You will therefore loose that match, and replace it by a false match between
@mymath{A_i} and @mymath{B_j}!
@@ -19976,10 +19976,10 @@ Here is how we adress this problem in Gnuastro's
Match program: as we are doing
Afterwards, for each @mymath{B_j} we can find the nearest element of A,
irrespective of how the inputs were sorted, or their dimensionality.
On the other hand, the basic parsing algorithm mentioned above is very
computationally expensive:
-@mymath{N\times M} distances have to measured, and calculating the distance
requires a square root and power of 2, which are not simple operations for the
CPU.
+@mymath{N\times M} distances have to measured, and calculating the distance
requires a square root and power of 2 (in 2 dimensions it would be
@mymath{\sqrt{(B_{ix}-A_{ix})^2+(B_{iy}-A_{iy})^2}}), which are not simple
operations for the CPU.
As a result, this basic algorithm will become terribly slow as your datasets
grow in size.
For example when N or M exceed hundreds of thousands (which is common in the
current days with datasets like the European Space Agency's Gaia mission).
-Therefore that basic parsing algoritm won't work and we need to use more
efficient ways to parse the two catalogs.
+Therefore that basic parsing algoritm will take too much time and we need to
use more efficient ways to parse the two catalogs.
Gnuastro's Match currently has two such algorithms:
@table @asis
@@ -19989,21 +19989,30 @@ To avoid the problem of calculating @mymath{N\times
M} Euclidean distances (that
@enumerate
@item
Sort the two datasets by their first coordinate.
-Therefore @mymath{A_i<A_j} (only in first coordinate; when @mymath{i<j}), and
similarly for the elements of B.
+Therefore @mymath{A_i<A_j} (only in first coordinate; when @mymath{i<j}), and
similarly, sort the elements of B based on the first coordinate.
@item
-Use the radial distance threshold to define a moving window of B over A.
-Therefore, within a single parsing of A, you can find all the elements in A
that are sufficiently near every @mymath{B_j}.
+Use the radial distance threshold to define the width of a moving interval
over both A and B.
+Therefore, with a single parsing of A, you can find all the elements in A that
are sufficiently near every element of B (while rejecting the ones that are too
distant when taking other dimensions into account).
@item
The nearest A within the subset that is nearest to @mymath{B_j} will be
considered as the match.
@end enumerate
+This method has some caveats:
+1) It requires sorting, which can again be slow.
+2) It can only be done on a single CPU thread! So it can't benefit from the
modern CPUs with many threads.
+3) There is no way to preserve intermediate information for future matches,
for example this can greatly help when one of the matched datasets is always
the same.
+
@item k-d tree based
-The k-d tree concept is much more abstract, but powerful (for example enabling
parallel processing, that was not possible in the sort-based method above).
+The k-d tree concept is much more abstract, but powerful (addressing all the
caveats of the sort-based method).
In short a k-d tree is a partitioning of a k-dimentional space.
+The k-d tree of table A is another table with the same number of rows, but
only two integer columns: the integers contain the row indexs (counting from
zero) of the left and right branch of that row.
For more on the k-d tree and Gnuastro's implementation of it, please see
@ref{K-d tree}.
-To avoid going too deep into theory, let's look at it from a user's
perspective: the k-d tree of table A is another table with the same number of
rows, but only two integer columns (the integers contain the row indexs of the
left and right branch of that row).
-Match will internally construct a k-d tree for catalog A (the first catalog
given to it) and use it for matching with catalog B.
+When given two catalogs (like the command below), Gnuastro's Match will
internally construct a k-d tree for catalog A (the first catalog given to it)
and use it for matching with catalog B.
+@example
+$ astmatch A.fits --ccol1=ra,dec B.fits --ccol2=ra,dec \
+ --aperture=1/3600
+@end example
However, optionally, you can also build the k-d tree of A and save it into a
file, with a separate call to Match (with @option{--kdtree=build} and
@option{--output=mykdtree.fits}).
This external k-d tree can be fed to Match later (to avoid having to
reconstruct it every time you want to match with the same first catalog; using
@option{--kdtree=mykdtree.fits}).
@@ -24452,35 +24461,28 @@ Blank value for string types (this is itself a
string, it isn't the
The functions below can be used to work with blank pixels.
@deftypefun void gal_blank_write (void @code{*pointer}, uint8_t @code{type})
-Write the blank value for the given @code{type} into the space that
-@code{pointer} points to. This can be used when the space is already
-allocated (for example one element in an array or a statically allocated
-variable).
+Write the blank value for the given @code{type} into the space that
@code{pointer} points to.
+This can be used when the space is already allocated (for example one element
in an array or a statically allocated variable).
@end deftypefun
@deftypefun {void *} gal_blank_alloc_write (uint8_t @code{type})
-Allocate the space required to keep the blank for the given data type
-@code{type}, write the blank value into it and return the pointer to it.
+Allocate the space required to keep the blank for the given data type
@code{type}, write the blank value into it and return the pointer to it.
@end deftypefun
@deftypefun void gal_blank_initialize (gal_data_t @code{*input})
-Initialize all the elements in the @code{input} dataset to the blank value
-that corresponds to its type. If @code{input} is a tile over a larger
-dataset, only the region that the tile covers will be set to blank.
+Initialize all the elements in the @code{input} dataset to the blank value
that corresponds to its type.
+If @code{input} isn't a string, and is a tile over a larger dataset, only the
region that the tile covers will be set to blank.
+For strings, the full dataset will be initialized.
@end deftypefun
@deftypefun void gal_blank_initialize_array (void @code{*array}, size_t
@code{size}, uint8_t @code{type})
-Initialize all the elements in the @code{array} to the blank value that
-corresponds to its type (identified with @code{type}), assuming the array
-has @code{size} elements.
+Initialize all the elements in the @code{array} to the blank value that
corresponds to its type (identified with @code{type}), assuming the array has
@code{size} elements.
@end deftypefun
@deftypefun {char *} gal_blank_as_string (uint8_t @code{type}, int
@code{width})
-Write the blank value for the given data type @code{type} into a string and
-return it. The space for the string is dynamically allocated so it must be
-freed after you are done with it. If @code{width!=0}, then the final string
-will be padded with white space characters to have the requested width if
-it is smaller.
+Write the blank value for the given data type @code{type} into a string and
return it.
+The space for the string is dynamically allocated so it must be freed after
you are done with it.
+If @code{width!=0}, then the final string will be padded with white space
characters to have the requested width if it is smaller.
@end deftypefun
@deftypefun int gal_blank_is (void @code{*pointer}, uint8_t @code{type})
diff --git a/lib/blank.c b/lib/blank.c
index dda0e91..5e33f97 100644
--- a/lib/blank.c
+++ b/lib/blank.c
@@ -107,7 +107,22 @@ gal_blank_alloc_write(uint8_t type)
void
gal_blank_initialize(gal_data_t *input)
{
- GAL_TILE_PARSE_OPERATE(input, NULL, 0, 0, {*i=b;});
+ size_t i;
+ char **strarr;
+
+ /* For strings, we will initialize the full array, for numerical data
+ types we will consider tiles. */
+ if(input->type==GAL_TYPE_STRING)
+ {
+ strarr=input->array;
+ for(i=0;i<input->size;++i)
+ {
+ if(strarr[i]) free(strarr[i]);
+ gal_checkset_allocate_copy(GAL_BLANK_STRING, &strarr[i]);
+ }
+ }
+ else
+ {GAL_TILE_PARSE_OPERATE(input, NULL, 0, 0, {*i=b;});}
}
diff --git a/lib/fits.c b/lib/fits.c
index d61fc9d..bdedfde 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -3091,6 +3091,13 @@ gal_fits_tab_info(char *filename, char *hdu, size_t
*numcols,
else
fits_binary_tform(value, &datatype, &repeat, NULL, &status);
+ /* Write the "repeat" element into 'allcols->minmapsize', but
+ also activate the repeat flag within the dataset.*/
+ allcols[index].minmapsize = repeat;
+ if(repeat==0)
+ allcols[index].flag
+ |= GAL_TABLEINTERN_FLAG_TFORM_REPEAT_IS_ZERO;
+
/* Write the type into the data structure. */
allcols[index].type=gal_fits_datatype_to_type(datatype, 1);
@@ -3108,7 +3115,14 @@ gal_fits_tab_info(char *filename, char *hdu, size_t
*numcols,
"standard in %s", filename, hdu, keyname, value,
__func__);
}
- allcols[index].disp_width=repeat;
+
+ /* TFORM's 'repeat' element can be zero (signifying a
+ column without any data)! In this case, we want the
+ output to be fully blank, so we need space for the
+ blank string. */
+ allcols[index].disp_width = ( repeat
+ ? repeat
+ : strlen(GAL_BLANK_STRING)+1);
}
}
}
@@ -3191,9 +3205,10 @@ gal_fits_tab_info(char *filename, char *hdu, size_t
*numcols,
/* This flag is not relevant for FITS tables. */
if(allcols[index].flag
- ==GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING)
+ & GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING)
{
- allcols[index].flag=0;
+ allcols[index].flag
+ &= ~GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING;
free(allcols[index].array);
}
}
@@ -3230,9 +3245,10 @@ gal_fits_tab_info(char *filename, char *hdu, size_t
*numcols,
/* This flag is not relevant for FITS tables. */
if(allcols[tmp_i->v].flag
- ==GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING)
+ & GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING)
{
- allcols[tmp_i->v].flag=0;
+ allcols[tmp_i->v].flag
+ &= ~GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING;
free(allcols[tmp_i->v].array);
}
}
@@ -3402,45 +3418,58 @@ fits_tab_read_onecol(void *in_prm)
}
}
- /* Allocate a blank value for the given type and read/store the
- column using CFITSIO. Note that for binary tables, we only need
- blank values for integer types. For binary floating point types,
- the FITS standard defines blanks as NaN (same as almost any other
- software like Gnuastro). However if a blank value is specified,
- CFITSIO will convert other special numbers like 'inf' to NaN
- also. We want to be able to distringuish 'inf' and NaN here, so
- for floating point types in binary tables, we won't define any
- blank value. In ASCII tables, CFITSIO doesn't read the 'NAN'
- values (that it has written itself) unless we specify a blank
- pointer/value. */
- isfloat = ( col->type==GAL_TYPE_FLOAT32
- || col->type==GAL_TYPE_FLOAT64 );
- blank = ( ( hdutype==BINARY_TBL && isfloat )
- ? NULL
- : gal_blank_alloc_write(col->type) );
- fits_read_col(fptr, gal_fits_type_to_datatype(col->type), indin+1,
- 1, 1, col->size, blank, col->array, &anynul, &status);
-
- /* In the ASCII table format, CFITSIO might not be able to read 'INF'
- or '-INF'. In this case, it will set status to 'BAD_C2D' or
- 'BAD_C2F'. So, we'll use our own parser for the column values. */
- if( hdutype==ASCII_TBL
- && isfloat
- && (status==BAD_C2D || status==BAD_C2F) )
+ /* If this column has a 'repeat' of zero, then just set all its
+ elements to its relevant blank type and don't call CFITSIO (there
+ is nothing for it to read, and it will crash with "FITSIO status =
+ 308: bad first element number First element to write is too large:
+ 1; max allowed value is 0"). */
+ if(p->allcols[indin].flag & GAL_TABLEINTERN_FLAG_TFORM_REPEAT_IS_ZERO)
+ gal_blank_initialize(col);
+
+ /* The column has non-zero width, read its contents. */
+ else
{
- fits_tab_read_ascii_float_special(p->filename, p->hdu,
- fptr, col, indin+1, p->numrows,
- p->minmapsize, p->quietmmap);
- status=0;
+ /* Allocate a blank value for the given type and read/store the
+ column using CFITSIO. Note that for binary tables, we only
+ need blank values for integer types. For binary floating point
+ types, the FITS standard defines blanks as NaN (same as almost
+ any other software like Gnuastro). However if a blank value is
+ specified, CFITSIO will convert other special numbers like
+ 'inf' to NaN also. We want to be able to distringuish 'inf'
+ and NaN here, so for floating point types in binary tables, we
+ won't define any blank value. In ASCII tables, CFITSIO doesn't
+ read the 'NAN' values (that it has written itself) unless we
+ specify a blank pointer/value. */
+ isfloat = ( col->type==GAL_TYPE_FLOAT32
+ || col->type==GAL_TYPE_FLOAT64 );
+ blank = ( ( hdutype==BINARY_TBL && isfloat )
+ ? NULL
+ : gal_blank_alloc_write(col->type) );
+ fits_read_col(fptr, gal_fits_type_to_datatype(col->type), indin+1,
+ 1, 1, col->size, blank, col->array, &anynul, &status);
+
+ /* In the ASCII table format, CFITSIO might not be able to read
+ 'INF' or '-INF'. In this case, it will set status to 'BAD_C2D'
+ or 'BAD_C2F'. So, we'll use our own parser for the column
+ values. */
+ if( hdutype==ASCII_TBL
+ && isfloat
+ && (status==BAD_C2D || status==BAD_C2F) )
+ {
+ fits_tab_read_ascii_float_special(p->filename, p->hdu,
+ fptr, col, indin+1, p->numrows,
+ p->minmapsize, p->quietmmap);
+ status=0;
+ }
+ gal_fits_io_error(status, NULL); /* After the 'status' correction. */
+
+ /* Clean up and sanity check (just note that the blank value for
+ strings, is an array of strings, so we need to free the
+ contents before freeing itself). */
+ if(col->type==GAL_TYPE_STRING)
+ {strarr=blank; free(strarr[0]);}
+ if(blank) free(blank);
}
- gal_fits_io_error(status, NULL); /* After the 'status' correction. */
-
- /* Clean up and sanity check (just note that the blank value for
- strings, is an array of strings, so we need to free the contents
- before freeing itself). */
- if(col->type==GAL_TYPE_STRING)
- {strarr=blank; free(strarr[0]);}
- if(blank) free(blank);
/* Everything is fine, put this column in the output array. */
p->colarray[indout]=col;
diff --git a/lib/gnuastro-internal/tableintern.h
b/lib/gnuastro-internal/tableintern.h
index 555282d..8e05531 100644
--- a/lib/gnuastro-internal/tableintern.h
+++ b/lib/gnuastro-internal/tableintern.h
@@ -52,12 +52,17 @@ __BEGIN_C_DECLS /* From C++ preparations */
-/* Flags for columns. */
-enum tableintern_flags
-{
- GAL_TABLEINTERN_FLAG_INVALID, /* Zero according to FITS standard. */
- GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING,
-};
+
+/* Number of bytes in the unsigned integer hosting the bit-flags ('flag'
+ element) of 'gal_data_t'. */
+#define GAL_TABLEINTERN_FLAG_SIZE 1
+
+/* Bit 0: If the FITS TFORM has a "repeat" value of 0. */
+#define GAL_TABLEINTERN_FLAG_TFORM_REPEAT_IS_ZERO 0x1
+
+/* Bit 1: If the 'array' element in this dataset is a blank string. */
+#define GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING 0x2
+
diff --git a/lib/table.c b/lib/table.c
index 7e6b4ca..7d21a67 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -58,7 +58,32 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
Note that other than the character strings (column name, units and
comments), nothing in the data structure(s) will be allocated by this
- function for the actual data (e.g., the 'array' or 'dsize' elements). */
+ function for the actual data (e.g., the 'array' or 'dsize' elements).
+
+ Here are the gal_data_t structure elements that are used in 'allcols':
+
+ *restrict array -> Blank value (if present).
+ type -> Type of column data.
+ ndim -> Blank number of dimensions (1)
+ *dsize -> Blank dimension lengths (1)
+ size -> Blank total size (1)
+ quietmmap -> ------------
+ *mmapname -> ------------
+ minmapsize -> Repeat (FITS Binary 'TFORM')
+ nwcs -> ------------
+ *wcs -> ------------
+ flag -> 'GAL_TABLEINTERN_FLAG_*' macros.
+ status -> ------------
+ *name -> Column name.
+ *unit -> Column unit.
+ *comment -> Column comments.
+ disp_fmt -> 'GAL_TABLE_DISPLAY_FMT' macros.
+ disp_width -> To keep width of string columns.
+ disp_precision -> ------------
+ *next -> ------------
+ *block -> ------------
+
+*/
gal_data_t *
gal_table_info(char *filename, char *hdu, gal_list_str_t *lines,
size_t *numcols, size_t *numrows, int *tableformat)
@@ -435,15 +460,8 @@ gal_table_read(char *filename, char *hdu, gal_list_str_t
*lines,
ignorecase, filename, hdu, colmatch);
/* Depending on the table format, read the columns into the output
- structure. Note that the functions here pop each index, read/store the
- desired column and pop the next, so after these functions, the output
- linked list will have the opposite order of its input 'indexll'
- list. So before calling any of them, we will first reverse the
- 'indexll' list, so the output data structure list will have the same
- order as the input list of desired columns. Also note that after these
- functions, the 'indexll' will be all freed (each popped element is
- actually freed).*/
- gal_list_sizet_reverse(&indexll);
+ structure. Also note that after these functions, the 'indexll' will be
+ all freed (each popped element is actually freed).*/
switch(tableformat)
{
case GAL_TABLE_FORMAT_TXT:
diff --git a/lib/tableintern.c b/lib/tableintern.c
index bd8a1c2..32730b0 100644
--- a/lib/tableintern.c
+++ b/lib/tableintern.c
@@ -428,7 +428,7 @@ gal_tableintern_read_blank(gal_data_t *col, char *blank)
correctly. If it isn't successful, then */
if( gal_type_from_string((void **)(&col->array), blank, col->type) )
{
- col->flag=GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING;
+ col->flag |= GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING;
gal_checkset_allocate_copy(blank, (char **)(&col->array));
}
else
diff --git a/lib/txt.c b/lib/txt.c
index 4ad22ae..b7b252d 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -536,7 +536,7 @@ txt_infoll_to_array(gal_data_t *datall, size_t *numdata)
/* Put all the information from 'data' into the respective part
of the array. About the pointers, instead of having to
allocate them again, we will just set them to NULL so
- 'gal_data_free' doesn't remove them.*/
+ 'gal_data_free' doesn't remove them. */
dataarr[ind].flag = data->flag; data->flag=0;
dataarr[ind].name = data->name; data->name=NULL;
dataarr[ind].unit = data->unit; data->unit=NULL;
@@ -750,7 +750,7 @@ txt_read_token(gal_data_t *data, gal_data_t *info, char
*token,
double *d = data->array, *db;
/* See if this token is blank. */
- int isblankstr = ( info->flag==GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING
+ int isblankstr = ( info->flag & GAL_TABLEINTERN_FLAG_ARRAY_IS_BLANK_STRING
? ( strcmp(info->array,token)==0 ? 1 : 0 )
: 0);
@@ -1102,6 +1102,7 @@ txt_read(char *filename, gal_list_str_t *lines, size_t
*dsize,
out->dsize=out->array=NULL;
}
}
+ gal_list_data_reverse(&out);
break;
- [gnuastro-commits] master 2877acb 05/19: Added fits files for testing in `during-dev-test-data`, (continued)
- [gnuastro-commits] master 2877acb 05/19: Added fits files for testing in `during-dev-test-data`, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master 48d760d 12/19: Library (match.h): k-d tree method discards regions with no overlap, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master d0b19b8 10/19: Match: make check script for k-d tree matching now executable, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master 095c788 13/19: Match: matched rows aren't permuted, but new column allocated, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master 9e258a8 14/19: Library (fits.h): reading table columns now done in parallel, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master 29f8b20 16/19: Table and Arithmetic: corrected some memory leaks, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master 8b17675 06/19: Corrected segmentation fault, included aperture, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master a7bfa5b 11/19: Match: k-d tree matching UI fixed, to do: finalizing docs and tests, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master f5d7d1a 19/19: Match: added tests, completed docs of new k-d tree based matching, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master 6f7ff61 08/19: Library (match.h): Using the old infra-structure for double-matches, Mohammad Akhlaghi, 2021/11/14
- [gnuastro-commits] master 68823e3 17/19: Library (fits.h): correctly reading columns of 0 width/repeat,
Mohammad Akhlaghi <=
- [gnuastro-commits] master a6b838c 18/19: Match: script to generate debugging input taken in bin/match/, Mohammad Akhlaghi, 2021/11/14