[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master 7a2a9c4: Table: New --inpolygon, --outpolygon
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master 7a2a9c4: Table: New --inpolygon, --outpolygon and --polygon options added |
Date: |
Sun, 10 May 2020 13:30:26 -0400 (EDT) |
branch: master
commit 7a2a9c4af056f3b71111e270ee4fb35069090280
Author: Sachin Kumar Singh <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>
Table: New --inpolygon, --outpolygon and --polygon options added
With the new `--inpolygon' and `--outpolygon' options, it is now possible
to select rows based on their position relative to a polygon (either inside
of it or outside). The `--polygon' option is shared between the two and is
used to specify the actual polygon.
Since we wanted Table's `--polygon' option to be parsed identially to
Crop's, the polygon parsing function of Crop was moved into the options.h
library as `gal_options_parse_colon_sep_csv' which is now used in both Crop
and Table.
---
NEWS | 3 +
bin/crop/args.h | 3 +-
bin/crop/main.h | 2 +-
bin/crop/onecrop.c | 106 --------------------------
bin/crop/onecrop.h | 3 -
bin/crop/ui.c | 26 +++++--
bin/table/args.h | 42 +++++++++++
bin/table/main.h | 5 ++
bin/table/table.c | 86 +++++++++++++++++++++
bin/table/ui.c | 73 +++++++++++++++---
bin/table/ui.h | 4 +
doc/gnuastro.texi | 30 ++++++++
lib/gnuastro-internal/options.h | 4 +
lib/options.c | 161 +++++++++++++++++++++++++++++++++++++++-
14 files changed, 422 insertions(+), 126 deletions(-)
diff --git a/NEWS b/NEWS
index 10ab205..5808dc8 100644
--- a/NEWS
+++ b/NEWS
@@ -50,6 +50,9 @@ See the end of the file for license conditions.
Table:
--equal: Can now work on columns with string type also.
--notequal: Can now work on columns with string type also.
+ --polygon: Polygon to use in `--inpolygon' or `--outpolygon'.
+ --inpolygon: Select rows that are inside the polygon of `--polygon'.
+ --outpolygon: Select rows that are outside the polygon of `--polygon'.
--catcolumn: Concatenate tables by column (keeping number of rows fixed).
--catcolhdu: Specify the HDU/extension of the FITS files of --catcolumn.
- New operators in column arithmetic:
diff --git a/bin/crop/args.h b/bin/crop/args.h
index 1c03781..86a22f6 100644
--- a/bin/crop/args.h
+++ b/bin/crop/args.h
@@ -265,7 +265,8 @@ struct argp_option program_options[] =
GAL_TYPE_STRING,
GAL_OPTIONS_RANGE_ANY,
GAL_OPTIONS_NOT_MANDATORY,
- GAL_OPTIONS_NOT_SET
+ GAL_OPTIONS_NOT_SET,
+ gal_options_parse_colon_sep_csv
},
{
"polygonout",
diff --git a/bin/crop/main.h b/bin/crop/main.h
index b167a5a..7b01e23 100644
--- a/bin/crop/main.h
+++ b/bin/crop/main.h
@@ -95,7 +95,7 @@ struct cropparams
char *namecol; /* Filename (without suffix) of crop col.*/
gal_list_str_t *coordcol; /* Column in cat containing coordinates. */
char *section; /* Section string. */
- char *polygon; /* Input string of polygon vertices. */
+ gal_data_t *polygon; /* Input string of polygon vertices. */
uint8_t polygonout; /* ==1: Keep the inner polygon region. */
uint8_t polygonsort; /* Don't sort polygon vertices. */
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index 24343a2..86e2e92 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -195,112 +195,6 @@ onecrop_parse_section(struct cropparams *p, size_t *dsize,
-
-void
-onecrop_parse_polygon(struct cropparams *p)
-{
- size_t dim=0;
- char *tailptr;
- char *pt=p->polygon;
- double read, *array;
- gal_list_f64_t *vertices=NULL;
-
- /* If control reached here, then the cropped region is not defined by its
- center. So it makes no sense to check if the center is blank. */
- p->checkcenter=0;
-
- /* Parse the string. */
- while(*pt!='\0')
- {
- switch(*pt)
- {
- case ',':
- ++dim;
- if(dim==2)
- error(EXIT_FAILURE, 0, "Extra `,` in `%s`", p->polygon);
- ++pt;
- break;
- case ':':
- if(dim==0)
- error(EXIT_FAILURE, 0, "not enough coordinates for at least "
- "one polygon vertex (in %s)", p->polygon);
- dim=0;
- ++pt;
- break;
- default:
- break;
- }
-
- /* strtod will skip white spaces if they are before a number,
- but not when they are before a : or ,. So we need to remove
- all white spaces. White spaces are usually put beside each
- other, so if one is encountered, go along the string until
- the white space characters finish. */
- if(isspace(*pt))
- ++pt;
- else
- {
- /* Read the number: */
- read=strtod(pt, &tailptr);
-
- /* Check if there actually was a number.
- printf("\n\n------\n%zu: %f (%s)\n", dim, read, tailptr);
- */
-
- /* Make sure if a number was read at all? */
- if(tailptr==pt) /* No number was read! */
- error(EXIT_FAILURE, 0, "%s could not be parsed as a floating "
- "point number", tailptr);
-
- /* Check if there are no extra characters in the number, for
- example we don't have a case like `1.00132.17', or
- 1.01i:2.0. Such errors are not uncommon when typing large
- numbers, and if ignored, they can lead to unpredictable
- results, so its best to abort and inform the user. */
- if( *tailptr!='\0'
- && !isspace(*tailptr)
- && strchr(":,", *tailptr)==NULL )
- error(EXIT_FAILURE, 0, "'%s' is an invalid floating point number "
- "sequence in the value to the `--polygon' option, error "
- "detected at '%s'", pt, tailptr);
-
- /* Add the read coordinate to the list of coordinates. */
- gal_list_f64_add(&vertices, read);
-
- /* The job here is done, start from tailptr */
- pt=tailptr;
- }
- }
-
- /* Put the coordinates into an array while reversing their order so they
- correspond to the user's order, then put it in the right place.*/
- array=gal_list_f64_to_array(vertices, 1, &p->nvertices);
- if(p->mode==IMGCROP_MODE_IMG) { p->ipolygon=array; p->wpolygon=NULL; }
- else { p->ipolygon=NULL; p->wpolygon=array; }
-
- /* The number of vertices is actually the number of nodes in the list
- divided by the dimension of the dataset (note that we were counting
- the dimension from 0. */
- p->nvertices/=(dim+1);
-
- /* For a check:
- {
- size_t i;
- double *polygon=p->mode==IMGCROP_MODE_IMG?p->ipolygon:p->wpolygon;
- for(i=0;i<p->nvertices;++i)
- printf("(%f, %f)\n", polygon[i*2], polygon[i*2+1]);
- }
- exit(0);
- */
-
- /* Clean up: */
- gal_list_f64_free(vertices);
-}
-
-
-
-
-
static void
onecrop_ipolygon_fl(double *ipolygon, size_t nvertices, long *fpixel,
long *lpixel)
diff --git a/bin/crop/onecrop.h b/bin/crop/onecrop.h
index f59202b..d2ef458 100644
--- a/bin/crop/onecrop.h
+++ b/bin/crop/onecrop.h
@@ -60,9 +60,6 @@ struct onecropparams
};
void
-onecrop_parse_polygon(struct cropparams *p);
-
-void
onecrop_name(struct onecropparams *crp);
void
diff --git a/bin/crop/ui.c b/bin/crop/ui.c
index 5806708..2df86fd 100644
--- a/bin/crop/ui.c
+++ b/bin/crop/ui.c
@@ -373,16 +373,32 @@ ui_read_check_only_options(struct cropparams *p)
in the proper format. */
if(p->polygon)
{
- onecrop_parse_polygon(p);
+ /* The number of vertices is half the total number of given values
+ (currently only 2D spaces are considered so each vertice has 2
+ coordinates. */
+ p->nvertices=p->polygon->size/2;
+
+ /* Basic sanity checks. */
if(p->nvertices<3)
error(EXIT_FAILURE, 0, "a polygon has to have 3 or more vertices, "
- "you have only given %zu (%s)", p->nvertices, p->polygon);
+ "you have only given %zu", p->nvertices);
if(p->polygonout && p->numin>1)
error(EXIT_FAILURE, 0, "currently in WCS mode, `--polygonout' can "
"only be set to zero when there is one image, you have given "
- "%zu images. For multiple images the region will be very large. "
- "It is best if you first crop out the larger region you want "
- "into one image, then mask the polygon", p->numin);
+ "%zu images. For multiple images the region will be very "
+ "large. It is best if you first crop out the larger region "
+ "you want into one image, then mask the polygon", p->numin);
+
+ /* Put the coordinates into an array while reversing their order so
+ they correspond to the user's order, then put it in the right
+ place.*/
+ darray=p->polygon->array;
+ if(p->mode==IMGCROP_MODE_IMG) {p->ipolygon=darray; p->wpolygon=NULL; }
+ else {p->ipolygon=NULL; p->wpolygon=darray;}
+
+ /* We know that the cropped region is not defined by its center. So
+ it makes no sense to check if the center is blank. */
+ p->checkcenter=0;
}
else
p->wpolygon=p->ipolygon=NULL;
diff --git a/bin/table/args.h b/bin/table/args.h
index e11cc5f..f66434b 100644
--- a/bin/table/args.h
+++ b/bin/table/args.h
@@ -154,6 +154,48 @@ struct argp_option program_options[] =
gal_options_parse_name_and_float64s
},
{
+ "inpolygon",
+ UI_KEY_INPOLYGON,
+ "STR,STR",
+ 0,
+ "Coord. columns that are inside `--polygon'.",
+ GAL_OPTIONS_GROUP_INPUT,
+ &p->inpolygon,
+ GAL_TYPE_STRING,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ gal_options_parse_csv_strings
+ },
+ {
+ "outpolygon",
+ UI_KEY_OUTPOLYGON,
+ "STR,STR",
+ 0,
+ "Coord. columns that are outside `--polygon'.",
+ GAL_OPTIONS_GROUP_INPUT,
+ &p->outpolygon,
+ GAL_TYPE_STRING,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ gal_options_parse_csv_strings
+ },
+ {
+ "polygon",
+ UI_KEY_POLYGON,
+ "FLT:FLT[,...]",
+ 0,
+ "Polygon for `--inpolygon' or `--outpolygon'.",
+ UI_GROUP_OUTROWS,
+ &p->polygon,
+ GAL_TYPE_STRING,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ gal_options_parse_colon_sep_csv
+ },
+ {
"equal",
UI_KEY_EQUAL,
"STR,FLT[,...]",
diff --git a/bin/table/main.h b/bin/table/main.h
index b1444e2..2f34834 100644
--- a/bin/table/main.h
+++ b/bin/table/main.h
@@ -38,6 +38,8 @@ enum select_types
{
/* Different types of row-selection */
SELECT_TYPE_RANGE, /* 0 by C standard */
+ SELECT_TYPE_INPOLYGON,
+ SELECT_TYPE_OUTPOLYGON,
SELECT_TYPE_EQUAL,
SELECT_TYPE_NOTEQUAL,
@@ -89,6 +91,9 @@ struct tableparams
uint8_t information; /* ==1: only print FITS information. */
uint8_t colinfoinstdout; /* ==1: print column metadata in CL. */
gal_data_t *range; /* Range to limit output. */
+ gal_data_t *inpolygon; /* Columns to check if inside polygon. */
+ gal_data_t *outpolygon; /* Columns to check if outside polygon. */
+ gal_data_t *polygon; /* Values of vertices of the polygon. */
gal_data_t *equal; /* Values to keep in output. */
gal_data_t *notequal; /* Values to not include in output. */
char *sort; /* Column name or number for sorting. */
diff --git a/bin/table/table.c b/bin/table/table.c
index ed28574..b2170e1 100644
--- a/bin/table/table.c
+++ b/bin/table/table.c
@@ -37,6 +37,7 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <gnuastro/table.h>
#include <gnuastro/qsort.h>
#include <gnuastro/pointer.h>
+#include <gnuastro/polygon.h>
#include <gnuastro/arithmetic.h>
#include <gnuastro/statistics.h>
#include <gnuastro/permutation.h>
@@ -136,6 +137,83 @@ table_selection_range(struct tableparams *p, gal_data_t
*col)
+/* Read column value of any type as a double for the polygon options. */
+static double
+selection_polygon_read_point(gal_data_t *col, size_t i)
+{
+ /* Check and assign the points to the points array. */
+ switch(col->type)
+ {
+ case GAL_TYPE_INT8: return (( int8_t *)col->array)[i];
+ case GAL_TYPE_UINT8: return (( uint8_t *)col->array)[i];
+ case GAL_TYPE_UINT16: return (( uint16_t *)col->array)[i];
+ case GAL_TYPE_INT16: return (( int16_t *)col->array)[i];
+ case GAL_TYPE_UINT32: return (( uint32_t *)col->array)[i];
+ case GAL_TYPE_INT32: return (( int32_t *)col->array)[i];
+ case GAL_TYPE_UINT64: return (( uint64_t *)col->array)[i];
+ case GAL_TYPE_INT64: return (( int64_t *)col->array)[i];
+ case GAL_TYPE_FLOAT32: return (( float *)col->array)[i];
+ case GAL_TYPE_FLOAT64: return (( double *)col->array)[i];
+ default:
+ error(EXIT_FAILURE, 0, "%s: type code %d not recognized",
+ __func__, col->type);
+ }
+
+ /* Control should not reach here. */
+ error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
+ "problem. Control should not reach the end of this function",
+ __func__, PACKAGE_BUGREPORT);
+ return NAN;
+}
+
+
+
+
+
+/* Mask the rows that are not in the given polygon. */
+static gal_data_t *
+table_selection_polygon(struct tableparams *p, gal_data_t *col1,
+ gal_data_t *col2, int in1out0)
+{
+ uint8_t *oarr;
+ double point[2];
+ gal_data_t *out=NULL;
+ size_t i, psize=p->polygon->size/2;
+
+ /* Allocate the output array: This array will have a `0' for the points
+ which are inside the polygon and `1' for those that are outside of it
+ (to be masked/removed from the input). */
+ out=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, col1->dsize, NULL, 0, -1, 1,
+ NULL, NULL, NULL);
+ oarr=out->array;
+
+ /* Loop through all the rows in the given columns and check the points.*/
+ for(i=0; i<col1->size; i++)
+ {
+ /* Read the column values as a double. */
+ point[0]=selection_polygon_read_point(col1, i);
+ point[1]=selection_polygon_read_point(col2, i);
+
+ /* For `--inpolygon', if point is inside polygon, put 0, otherwise
+ 1. Note that we are building a mask for the rows that must be
+ discarded, so we want `1' for the points we don't want. */
+ oarr[i] = (in1out0
+ ? !gal_polygon_is_inside(p->polygon->array, point, psize)
+ : gal_polygon_is_inside(p->polygon->array, point, psize));
+
+ /* For a check
+ printf("(%f,%f): %s, %u\n", point[0], point[1], oarr[i]);
+ */
+ }
+
+ /* Return the output column. */
+ return out;
+}
+
+
+
+
+
/* Given a string dataset and a single string, return a `uint8_t' array
with the same size as the string dataset that has a `1' for all the
elements that are equal. */
@@ -284,6 +362,14 @@ table_selection(struct tableparams *p)
addmask=table_selection_range(p, tmp->col);
break;
+ /* `--inpolygon' and `--outpolygon' need two columns. */
+ case SELECT_TYPE_INPOLYGON:
+ case SELECT_TYPE_OUTPOLYGON:
+ addmask=table_selection_polygon(p, tmp->col, tmp->next->col,
+ tmp->type==SELECT_TYPE_INPOLYGON);
+ tmp=tmp->next;
+ break;
+
case SELECT_TYPE_EQUAL:
addmask=table_selection_equal_or_notequal(p, tmp->col, 0);
break;
diff --git a/bin/table/ui.c b/bin/table/ui.c
index 1fc3517..38556a7 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -249,6 +249,28 @@ ui_read_check_only_options(struct tableparams *p)
"be smaller than the second (%g)", darr[0], darr[1]);
}
+ /* Basic checks for `--inpolygon' or `--outpolygon'. */
+ if(p->inpolygon || p->outpolygon)
+ {
+ if(p->inpolygon && p->outpolygon)
+ error(EXIT_FAILURE, 0, "`--inpolygon' and `--outpolygon' options "
+ "cannot be called together");
+
+ if(p->inpolygon && p->inpolygon->size!=2)
+ error(EXIT_FAILURE, 0, "two columns (for coordinates) can "
+ "be given to `--inpolygon'");
+
+ if(p->outpolygon && p->outpolygon->size!=2)
+ error(EXIT_FAILURE, 0, "two columns (for coordinates) can "
+ "be given to `--outpolygon'");
+
+ if(p->polygon==NULL)
+ error(EXIT_FAILURE, 0, "no polygon specified for `--inpolygon' or "
+ "`--outpolygon'! Please provide the vertices of the desired "
+ "polygon with the `--polygon' option in this format: "
+ "v1x,v1y:v2x,v2y:v3x,v3y:...");
+ }
+
/* Make sure `--head' and `--tail' aren't given together. */
if(p->head!=GAL_BLANK_SIZE_T && p->tail!=GAL_BLANK_SIZE_T)
@@ -676,24 +698,52 @@ ui_check_select_sort_before(struct tableparams *p,
gal_list_str_t *lines,
size_t *sortindout, size_t **selectindout_out,
size_t **selecttypeout_out)
{
- gal_data_t *dtmp, *allcols;
- size_t sortind=GAL_BLANK_SIZE_T;
+ char **strarr;
gal_list_sizet_t *tmp, *indexll;
gal_list_str_t *stmp, *add=NULL;
int tableformat, selecthasname=0;
+ size_t one=1, sortind=GAL_BLANK_SIZE_T;
size_t *selectind=NULL, *selecttype=NULL;
size_t *selectindout=NULL, *selecttypeout=NULL;
size_t i, j, k, *s, *sf, allncols, numcols, numrows;
+ gal_data_t *dtmp, *allcols, *inpolytmp=NULL, *outpolytmp=NULL;
/* Important note: these have to be in the same order as the `enum
- select_types' in `main.h'. */
- gal_data_t *select[SELECT_TYPE_NUMBER]={p->range, p->equal, p->notequal};
+ select_types' in `main.h'. We'll fill the two polygon elements
+ later. */
+ gal_data_t *select[SELECT_TYPE_NUMBER]={p->range, NULL, NULL,
+ p->equal, p->notequal};
+
+
+ /* The inpolygon dataset is currently a single dataset with two elements
+ (strings). But we need to have it as two linked datasets with a set
+ name. */
+ if(p->inpolygon)
+ {
+ strarr=p->inpolygon->array;
+ inpolytmp=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, &one, NULL, 1, -1, 1,
+ strarr[0], NULL, NULL);
+ inpolytmp->next=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, &one, NULL,
+ 1, -1, 1, strarr[1], NULL, NULL);
+ select[SELECT_TYPE_INPOLYGON]=inpolytmp;
+ }
+ if(p->outpolygon)
+ {
+ strarr=p->outpolygon->array;
+ outpolytmp=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, &one, NULL, 1, -1, 1,
+ strarr[0], NULL, NULL);
+ outpolytmp->next=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, &one, NULL,
+ 1, -1, 1, strarr[1], NULL, NULL);
+ select[SELECT_TYPE_OUTPOLYGON]=outpolytmp;
+ }
/* Allocate necessary spaces. */
if(p->selection)
{
*nselect = ( gal_list_data_number(p->range)
+ + gal_list_data_number(inpolytmp)
+ + gal_list_data_number(outpolytmp)
+ gal_list_data_number(p->equal)
+ gal_list_data_number(p->notequal) );
selectind=gal_pointer_allocate(GAL_TYPE_SIZE_T, *nselect, 0,
@@ -712,7 +762,7 @@ ui_check_select_sort_before(struct tableparams *p,
gal_list_str_t *lines,
/* See if the given columns are numbers or names. */
i=0;
- if(p->sort) sortind = ui_check_select_sort_read_col_ind(p->sort);
+ if(p->sort) sortind=ui_check_select_sort_read_col_ind(p->sort);
if(p->selection)
for(k=0;k<SELECT_TYPE_NUMBER;++k)
for(dtmp=select[k];dtmp!=NULL;dtmp=dtmp->next)
@@ -740,7 +790,8 @@ ui_check_select_sort_before(struct tableparams *p,
gal_list_str_t *lines,
for(i=0;i<*nselect;++i)
if(selectind[i]!=GAL_BLANK_SIZE_T && selectind[i]>=numcols)
error(EXIT_FAILURE, 0, "%s has %zu columns, less than the column "
- "number given to `--range', `--equal', or `--sort' (%zu)",
+ "number given to `--range', `--inpolygon', `--outpolygon', "
+ "`--equal', or `--sort' (%zu)",
gal_fits_name_save_as_string(p->filename, p->cp.hdu), numcols,
selectind[i]);
@@ -873,6 +924,8 @@ ui_check_select_sort_before(struct tableparams *p,
gal_list_str_t *lines,
if(selectind) free(selectind);
if(selecttype) free(selecttype);
gal_data_array_free(allcols, numcols, 0);
+ if(inpolytmp) gal_list_data_free(inpolytmp);
+ if(outpolytmp) gal_list_data_free(outpolytmp);
}
@@ -978,13 +1031,15 @@ ui_preparations(struct tableparams *p)
/* If any kind of row-selection is requested set `p->selection' to 1. */
- p->selection = p->range || p->equal || p->notequal;
+ p->selection = ( p->range || p->inpolygon || p->outpolygon || p->equal
+ || p->notequal );
+
/* If row sorting or selection are requested, see if we should read any
extra columns. */
if(p->selection || p->sort)
- ui_check_select_sort_before(p, lines, &nselect, &origoutncols, &sortindout,
- &selectindout, &selecttypeout);
+ ui_check_select_sort_before(p, lines, &nselect, &origoutncols,
+ &sortindout, &selectindout, &selecttypeout);
/* If we have any arithmetic operations, we need to make sure how many
diff --git a/bin/table/ui.h b/bin/table/ui.h
index 72fa2d5..9d27a80 100644
--- a/bin/table/ui.h
+++ b/bin/table/ui.h
@@ -61,8 +61,12 @@ enum option_keys_enum
UI_KEY_TAIL = 't',
UI_KEY_CATCOLUMN = 'C',
UI_KEY_CATCOLHDU = 'u',
+
/* Only with long version (start with a value 1000, the rest will be set
automatically). */
+ UI_KEY_POLYGON = 1000,
+ UI_KEY_INPOLYGON,
+ UI_KEY_OUTPOLYGON,
};
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 329feb9..7129279 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -9368,6 +9368,36 @@ This is good when you just want to select using one
column's values, but don't n
For one example of using this option, see the example under
@option{--sigclip-median} in @ref{Invoking aststatistics}.
+@item --inpolygon=STR1,STR2
+Only return rows where the given coordinates are inside the polygon specified
by the @option{--polygon} option.
+The coordinate columns are the given @code{STR1} and @code{STR2} columns, they
can be a column name or counter (see @ref{Selecting table columns}).
+
+Note that the chosen columns doesn't have to be in the output columns (which
are specified by the @code{--column} option).
+For example if we want to select rows in the polygon specified in @ref{Dataset
inspection and cropping}, this option can be used like this (you can remove the
double quotations and write them all in one line if you remove the white-spaces
around the colon separating the column vertices):
+
+@example
+asttable table.fits --inpolygon=RA,DEC \
+ --polygon="53.187414,-27.779152 \
+ : 53.159507,-27.759633 \
+ : 53.134517,-27.787144 \
+ : 53.161906,-27.807208" \
+@end example
+
+@cartouche
+@noindent
+@strong{Flat/Euclidean space: } The @option{--inpolygon} option assumes a
flat/Euclidean space so it is only correct for RA and Dec when the polygon size
is very small like the example above.
+If your polygon is a degree or larger, it may not return correct results.
+We are working on other options for this.
+@end cartouche
+
+@item --outpolygon=STR1,STR2
+Only return rows where the given coordinates are outside the polygon specified
by the @option{--polygon} option.
+This option is very similar to the @option{--inpolygon} option, so see the
description there for more.
+
+@item --polygon=FLT:FLT,...
+The polygon to use for the @code{--inpolygon} and @option{--outpolygon}
options.
+The values to this option is parsed in the same way that the Crop program, see
its description there for more: @ref{Crop options}.
+
@item -e STR,INT/FLT,...
@itemx --equal=STR,INT/FLT,...
Only output rows that are equal to the given number(s) in the given column.
diff --git a/lib/gnuastro-internal/options.h b/lib/gnuastro-internal/options.h
index dd0e678..ec02c61 100644
--- a/lib/gnuastro-internal/options.h
+++ b/lib/gnuastro-internal/options.h
@@ -315,6 +315,10 @@ void *
gal_options_parse_name_and_float64s(struct argp_option *option, char *arg,
char *filename, size_t lineno, void *junk);
+void *
+gal_options_parse_colon_sep_csv(struct argp_option *option, char *arg,
+ char *filename, size_t lineno, void *junk);
+
/**********************************************************************/
/************ Command-line options ***************/
diff --git a/lib/options.c b/lib/options.c
index f93fc60..7e5599c 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -1152,7 +1152,7 @@ gal_options_parse_name_and_values(struct argp_option
*option, char *arg,
/* We want to print the stored values. */
if(lineno==-1)
{
- /* Set the value pointer to `dataset'. */
+ /* Set the value pointer to `existing'. */
existing=*(gal_data_t **)(option->value);
if(str0_f641) darray = existing->array;
else strarr = existing->array;
@@ -1173,6 +1173,8 @@ gal_options_parse_name_and_values(struct argp_option
*option, char *arg,
if(str0_f641) nc += sprintf(sstr+nc, "%g,", darray[i]);
else nc += sprintf(sstr+nc, "%s,", strarr[i]);
}
+
+ /* Finish the string. */
sstr[nc-1]='\0';
/* Copy the string into a dynamically allocated space, because it
@@ -1259,6 +1261,163 @@ gal_options_parse_name_and_float64s(struct argp_option
*option, char *arg,
+/* Parse strings like this: `num1,num2:num3,n4:num5,num6' and return it as
+ a data container array: all elements are simply placed after each other
+ in the array. */
+static gal_data_t *
+options_parse_colon_sep_csv(char *instring, char *filename, size_t lineno)
+{
+ char *tailptr;
+ gal_data_t *out;
+ char *pt=instring;
+ size_t dim=0, size;
+ double read, *array;
+ gal_list_f64_t *vertices=NULL;
+
+ /* Parse the string. */
+ while(*pt!='\0')
+ {
+ switch(*pt)
+ {
+ case ',':
+ ++dim;
+ if(dim==2)
+ error_at_line(EXIT_FAILURE, 0, filename, lineno,
+ "Extra `,` in `%s`", instring);
+ ++pt;
+ break;
+ case ':':
+ if(dim==0)
+ error_at_line(EXIT_FAILURE, 0, filename, lineno,
+ "not enough coordinates for at least "
+ "one polygon vertex (in %s)", instring);
+ dim=0;
+ ++pt;
+ break;
+ default:
+ break;
+ }
+
+ /* strtod will skip white spaces if they are before a number,
+ but not when they are before a : or ,. So we need to remove
+ all white spaces. White spaces are usually put beside each
+ other, so if one is encountered, go along the string until
+ the white space characters finish. */
+ if(isspace(*pt))
+ ++pt;
+ else
+ {
+ /* Read the number: */
+ read=strtod(pt, &tailptr);
+
+ /* Check if there actually was a number.
+ printf("\n\n------\n%zu: %f (%s)\n", dim, read, tailptr);
+ */
+
+ /* Make sure if a number was read at all? */
+ if(tailptr==pt) /* No number was read! */
+ error_at_line(EXIT_FAILURE, 0, filename, lineno,
+ "%s could not be parsed as a floating point "
+ "number", tailptr);
+
+ /* Check if there are no extra characters in the number, for
+ example we don't have a case like `1.00132.17', or
+ 1.01i:2.0. Such errors are not uncommon when typing large
+ numbers, and if ignored, they can lead to unpredictable
+ results, so its best to abort and inform the user. */
+ if( *tailptr!='\0'
+ && !isspace(*tailptr)
+ && strchr(":,", *tailptr)==NULL )
+ error_at_line(EXIT_FAILURE, 0, filename, lineno,
+ "'%s' is an invalid floating point number "
+ "sequence in the value to the `--polygon' "
+ "option, error detected at '%s'", pt, tailptr);
+
+ /* Add the read coordinate to the list of coordinates. */
+ gal_list_f64_add(&vertices, read);
+
+ /* The job here is done, start from tailptr */
+ pt=tailptr;
+ }
+ }
+
+ /* Convert the list to an array, put it in a data structure, clean up and
+ return. */
+ array=gal_list_f64_to_array(vertices, 1, &size);
+ out=gal_data_alloc(array, GAL_TYPE_FLOAT64, 1, &size, NULL, 0, -1, 1,
+ NULL, NULL, NULL);
+ gal_list_f64_free(vertices);
+ return out;
+}
+
+
+
+
+
+/* Parse strings that are given to a function in this format
+ `num1,num2:num3,n4:num5,num6' */
+void *
+gal_options_parse_colon_sep_csv(struct argp_option *option, char *arg,
+ char *filename, size_t lineno, void *junk)
+{
+ double *darray;
+ size_t i, nc, size;
+ gal_data_t *tmp, *dataset, *existing;
+ char *str, sstr[GAL_OPTIONS_STATIC_MEM_FOR_VALUES];
+
+ /* We want to print the stored values. */
+ if(lineno==-1)
+ {
+ /* Set the value pointer to `existing'. */
+ existing=*(gal_data_t **)(option->value);
+ darray=existing->array;
+
+ /* Start printing the values. */
+ nc=0;
+ size=existing->size;
+ for(i=0;i<size;i+=2)
+ {
+ /* Make sure we aren't passing the allocated space. */
+ if( nc > GAL_OPTIONS_STATIC_MEM_FOR_VALUES-100 )
+ error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s so we "
+ "can address the problem. The number of necessary "
+ "characters in the statically allocated string has become "
+ "too close to %d", __func__, PACKAGE_BUGREPORT,
+ GAL_OPTIONS_STATIC_MEM_FOR_VALUES);
+
+ /* Print the two values in the expected format. */
+ nc += sprintf(sstr+nc, "%.6f,%.6f%s", darray[i], darray[i+1],
+ (i==(size-2) ? "" : ":") );
+ }
+
+ /* Finish the string. */
+ sstr[nc-1]='\0';
+
+ /* Copy the string into a dynamically allocated space, because it
+ will be freed later.*/
+ gal_checkset_allocate_copy(sstr, &str);
+ return str;
+ }
+ else
+ {
+ /* Parse the desired format and put it in this option's pointer. */
+ dataset=options_parse_colon_sep_csv(arg, filename, lineno);
+
+ /* Add the given dataset to the end of an existing dataset. */
+ existing = *(gal_data_t **)(option->value);
+ if(existing)
+ {
+ for(tmp=existing;tmp!=NULL;tmp=tmp->next)
+ if(tmp->next==NULL) { tmp->next=dataset; break; }
+ }
+ else
+ *(gal_data_t **)(option->value) = dataset;
+
+ /* In this scenario, there is no NULL value. */
+ return NULL;
+ }
+}
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnuastro-commits] master 7a2a9c4: Table: New --inpolygon, --outpolygon and --polygon options added,
Mohammad Akhlaghi <=