[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnuastro-commits] master 1817ff60: MakeCatalog: per-slice measurements
From: |
Mohammad Akhlaghi |
Subject: |
[gnuastro-commits] master 1817ff60: MakeCatalog: per-slice measurements in vector columns |
Date: |
Sat, 29 Apr 2023 14:05:12 -0400 (EDT) |
branch: master
commit 1817ff60535dc011bb51667bf8d849232f4020b0
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>
MakeCatalog: per-slice measurements in vector columns
Until now, MakeCatalog would write per-slice measurements (like the
spectrum of an object in an IFU cube) in different HDUs of the output
file. This was extremely slow and very inconvenient.
With this commit, MakeCatalog now writes such measurements as vector
columns in its single output table and the old '--spectrum' column has been
removed. It has been replaced by separate measurements with this format:
'--*-in-slice'.
The following changes have also been made as part of this commit:
- Book: Added new tutorial to show-case this feature. Which is also a good
demonstration of vector column management.
- Library (spectrallines.h): added a much larger database of lines.
- CosmicCalculator: new option to specify the line unit to input/output.
---
NEWS | 46 +-
bin/arithmetic/arithmetic.c | 49 +-
bin/convertt/ui.c | 3 +-
bin/cosmiccal/args.h | 19 +-
bin/cosmiccal/astcosmiccal.conf | 3 +
bin/cosmiccal/cosmiccal.c | 29 +-
bin/cosmiccal/main.h | 3 +
bin/cosmiccal/ui.c | 169 ++-
bin/cosmiccal/ui.h | 3 +-
bin/fits/ui.c | 2 +-
bin/match/ui.c | 13 +-
bin/mkcatalog/args.h | 150 ++-
bin/mkcatalog/columns.c | 509 +++++++--
bin/mkcatalog/main.h | 38 +-
bin/mkcatalog/mkcatalog.c | 241 ++---
bin/mkcatalog/mkcatalog.h | 7 +-
bin/mkcatalog/parse.c | 611 +++++------
bin/mkcatalog/ui.c | 303 ++----
bin/mkcatalog/ui.h | 12 +
bin/noisechisel/astnoisechisel-3d.conf | 4 +-
bin/script/fits-view.in | 16 +-
bin/segment/astsegment-3d.conf | 4 +-
bin/statistics/ui.c | 2 +-
bin/table/args.h | 45 +-
bin/table/arithmetic.c | 12 +-
bin/table/main.h | 6 +-
bin/table/table.c | 119 +-
bin/table/ui.c | 209 ++--
bin/table/ui.h | 8 +-
configure.ac | 3 +-
doc/gnuastro.texi | 1853 ++++++++++++++++++++++++--------
lib/fits.c | 25 +-
lib/gnuastro-internal/options.h | 13 +-
lib/gnuastro/list.h | 2 +-
lib/gnuastro/permutation.h | 3 +-
lib/gnuastro/speclines.h | 886 ++++++++++++---
lib/list.c | 9 +-
lib/makeplugin.c | 6 +-
lib/options.c | 167 ++-
lib/permutation.c | 117 ++
lib/speclines.c | 1133 ++++++++++++++++---
lib/txt.c | 12 +-
tests/during-dev.sh | 5 +-
43 files changed, 5056 insertions(+), 1813 deletions(-)
diff --git a/NEWS b/NEWS
index bb8c8f75..8322825b 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,11 @@ See the end of the file for license conditions.
Raul Infante-Sainz, Samane Raji, Zahra Sharbaf, Zohreh Ghaffari.
Book:
+ - New tutorial on detection and spectrum extraction from 3D data has
+ been added in the "Tutorials" chapter. It uses a MUSE cube and
+ demonstrates how to subtract the continuum, run NoiseChisel, Segment
+ and MakeCatalog for obtaining spectra and creating pseudo narrow-band
+ images of emission-lines.
- New "Shell tips" sub-section added (under the "Command-line" section
of the "Common program behavior" chapter). This sub-section contains
useful shell tips and tricks that can be useful when using Gnuastro's
@@ -72,6 +77,15 @@ See the end of the file for license conditions.
- f32: same as 'float32' (to convert to 32-bit floating point).
- f64: same as 'float64' (to convert to 64-bit floating point).
+ CosmicCalculator:
+ - Spectral line database has been increased to 235 spectral lines in the
+ UV and optical (previously only had 41 lines!) from:
+ http://astronomy.nmsu.edu/drewski/tableofemissionlines.html
+ To see the full list, run 'astcosmiccal --listlines'.
+ --lineunit: allows you to specify the units of the displayed spectral
+ line wavelengths. Currently, it take four units: 'm', 'micron', 'nm'
+ and 'angstrom'. We can add any other unit easily, just let us know.
+
Crop:
--append: if the output file already exists, append the cropped image
HDU to the already existing HDUs of the file. Without this option, any
@@ -98,6 +112,20 @@ See the end of the file for license conditions.
arcsec^2) of the sigma-clipped standard deviation of the values. This
can be used to find the reliable surface brightness of a radial
profile for example.
+ --sum-in-slice: [3D in; vector out] Sum of values in each slice.
+ --sum-err-in-slice: [3D in; vector out] Error in '--suminslice'.
+ --area-in-slice: [3D input; vector out] Number of labeled in each slice.
+ --sum-proj-in-slice: [3D input; vector out] Sum of projected area
+ in each slice.
+ --area-proj-in-slice: [3D in; vector out] Number of voxels that are used
+ in '--sum-proj-in-slice'.
+ --sum-proj-err-in-slice: [3D in; vector out] Error of '--sum-proj-in-slice'.
+ --area-other-in-slice: [3D in; vector out] Area of other label in
+ projected area on each slice.
+ --sum-other-in-slice: [3D in; vector out] Sum of other label in
+ projected area on each slice.
+ --sum-other-err-in-slice: [3D in; vector out] Area in
+ '--sum-other-in-slice'.
NoiseChisel:
--outliernumngb: the number of neighboring tiles to reject those that
@@ -118,7 +146,7 @@ See the end of the file for license conditions.
Table:
- Vector columns with multiple values per column are now supported. The
following features have been added to help working on vector columns:
- --Book: a new "Vector columns" section has been added under the Table
+ - Book: a new "Vector columns" section has been added under the Table
program which descibes the core concepts and usage examples of the
options below.
--information: also identifies vector columns (a column with more than
@@ -130,6 +158,10 @@ See the end of the file for license conditions.
separate single-valued columns.
--keepvectfin: do not delete the input columns to '--tovector' and
'--fromvector'.
+ --rowfirst: do row-based operations before column-based operations (by
+ default column-based operations are done first).
+ --transpose: column-based operator to transpose vector columns into a
+ new table that has the inverse number of rows and columns.
--txteasy: (or '-Y') when output is a plain-text file or just gets
printed on standard output (terminal), all floating point columns are
printed in fixed point notation (as in '123.456') instead of the
@@ -139,7 +171,6 @@ See the end of the file for license conditions.
readability, but be careful with some scenarios (for example
'1.23e-120', which will show only as '0.0'!). For more, see the
changes in Table in this version.
-
- New column arithmetic operator:
- sorted-to-interval: return two columns from a single (sorted) input,
containing the minimum and maximum values of an interval. The
@@ -222,6 +253,12 @@ See the end of the file for license conditions.
installing pre-built binaries it through services like PyPI, so they
won't be needing it either.
+ CosmicCalculator:
+ - Given the major increase of the spectral line database, the old line
+ names have been changed to accommodate the full database. For example
+ 'H-alpha' has replaced 'halpha'. Please run 'astcosmiccal --listlines'
+ to see the new names for the previous lines.
+
MakeCatalog:
- "Sum" used instead of "brightness"
--sum: new name for the old '--brightness' column. "Brightness" has a
@@ -334,6 +371,9 @@ See the end of the file for license conditions.
changed '--sum' in MakeCatalog (above) for more.
Table:
+ - Given the newly added vector columns, the precedence on operations has
+ been updated. Please read the "Operation precedence in Table" section
+ of the book.
- To avoid potential loss of information in floating point columns, when
printing the columns to standard output (in the terminal) or saving in
a plain-text file, the default floating point formats are now printed
@@ -356,6 +396,8 @@ See the end of the file for license conditions.
Library:
- gal_blank_remove_rows: new 'onlydim0' argument to ignore vector columns
when checking for blanks.
+ - gal_list_str_cat: new 'delimiter' argument to specify the character for
+ printing between the separate string nodes in the single output string.
- gal_txt_write: new 'tab0_img1' argument. Until now, this function would
distinguish between images and tables using the dimensions of the
input. But with the addition of vector columns in tables (that have 2
diff --git a/bin/arithmetic/arithmetic.c b/bin/arithmetic/arithmetic.c
index 2e88412b..8aaf6263 100644
--- a/bin/arithmetic/arithmetic.c
+++ b/bin/arithmetic/arithmetic.c
@@ -384,18 +384,16 @@ wrapper_for_filter(struct arithmeticparams *p, char
*token, int operator)
pop the necessary number of operands. */
nparams = ndim + (issigclip ? 2 : 0 );
for(i=0;i<nparams;++i)
- gal_list_data_add(¶ms_list, operands_pop(p, token));
-
-
- /* Make sure the parameters only have single values. */
- i=0;
- for(tmp=params_list; tmp!=NULL; tmp=tmp->next)
{
- ++i;
- if(tmp->size!=1)
+ /* Add this to the list of parameters. */
+ gal_list_data_add(¶ms_list, operands_pop(p, token));
+
+ /* Make sure it only has a single element. */
+ if(params_list->size!=1)
error(EXIT_FAILURE, 0, "the parameters given to the filtering "
- "operators can only be numbers. Value number %zu has %zu "
- "elements, so its an array", i, tmp->size);
+ "operators can only be numbers. Operand number %zu after "
+ "the main input has %zu elements, so its an array", i,
+ params_list->size);
}
@@ -416,10 +414,23 @@ wrapper_for_filter(struct arithmeticparams *p, char
*token, int operator)
gal_data_free(tmp);
}
-
- /* If the input only has one element, filtering makes no sense, so don't
- waste time, just add the input onto the stack. */
- if(afp.input->size==1) afp.out=afp.input;
+ /* If the input only has one element, it is most probably and error (the
+ user has confused the parameters with the input dataset). So report a
+ warning filtering makes no sense, so don't waste time, just add the
+ input onto the stack. */
+ if(afp.input->size==1)
+ {
+ /* Inform the user that this is suspicious. */
+ if(p->cp.quiet==0)
+ error(EXIT_SUCCESS, 0, "WARNING: the first popped operand to the "
+ "filtering operators has a single element! This is most "
+ "probably a typo in the order of operands! Recall that the "
+ "filtering operators need the main input image/cube as the "
+ "first popped operand");
+
+ /* Set the input as the output. */
+ afp.out=afp.input;
+ }
else
{
/* Allocate an array for the size of the filter and fill it in. The
@@ -451,8 +462,8 @@ wrapper_for_filter(struct arithmeticparams *p, char *token,
int operator)
/* If the width is larger than the input's size, change the width
to the input's size. */
if( fsize[i] > afp.input->dsize[i] )
- error(EXIT_FAILURE, 0, "%s: the filter size along dimension %zu "
- "(%zu) is greater than the input's length in that "
+ error(EXIT_FAILURE, 0, "%s: the filter size along dimension "
+ "%zu (%zu) is greater than the input's length in that "
"dimension (%zu)", __func__, i, fsize[i],
afp.input->dsize[i]);
@@ -494,8 +505,8 @@ wrapper_for_filter(struct arithmeticparams *p, char *token,
int operator)
break;
default:
- error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s to fix "
- "the problem. The 'operator' code %d is not recognized",
+ error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s to "
+ "fix the problem. The 'operator' code %d is not recognized",
PACKAGE_BUGREPORT, __func__, operator);
}
@@ -520,8 +531,8 @@ wrapper_for_filter(struct arithmeticparams *p, char *token,
int operator)
/* Clean up and add the output on top of the stack. */
gal_data_free(zero);
- gal_data_free(afp.input);
gal_list_data_free(params_list);
+ if(afp.input!=afp.out) gal_data_free(afp.input); /* Single-element. */
}
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index 45871ad5..478ac465 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -1231,7 +1231,8 @@ ui_set_output(struct converttparams *p)
}
/* Check if the output already exists and remove it if allowed. */
- gal_checkset_writable_remove(cp->output, p->inputnames->v, 0,
+ gal_checkset_writable_remove(cp->output,
+ p->inputnames ? p->inputnames->v : NULL, 0,
cp->dontdelete);
}
diff --git a/bin/cosmiccal/args.h b/bin/cosmiccal/args.h
index 4bb404c0..c7818814 100644
--- a/bin/cosmiccal/args.h
+++ b/bin/cosmiccal/args.h
@@ -346,7 +346,7 @@ struct argp_option program_options[] =
UI_KEY_LISTLINES,
0,
0,
- "List known lines and rest frame wavelength.",
+ "List pre-defined lines at rest frame.",
UI_GROUP_SPECTRAL_LINES,
&p->listlines,
GAL_OPTIONS_NO_ARG_TYPE,
@@ -359,7 +359,7 @@ struct argp_option program_options[] =
UI_KEY_LISTLINESATZ,
0,
0,
- "List known spectral lines at given redshift.",
+ "List pre-defined lines at the given redshift.",
UI_GROUP_SPECTRAL_LINES,
&p->listlinesatz,
GAL_OPTIONS_NO_ARG_TYPE,
@@ -367,6 +367,19 @@ struct argp_option program_options[] =
GAL_OPTIONS_NOT_MANDATORY,
GAL_OPTIONS_NOT_SET
},
+ {
+ "lineunit",
+ UI_KEY_LINEUNIT,
+ "STR",
+ 0,
+ "Unit ('angstrom', 'nm', 'microm' or 'm').",
+ UI_GROUP_SPECTRAL_LINES,
+ &p->lineunit,
+ GAL_TYPE_STRING,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ },
{
"lineatz",
UI_KEY_LINEATZ,
@@ -382,8 +395,6 @@ struct argp_option program_options[] =
ui_add_to_single_value,
},
-
-
{0}
};
diff --git a/bin/cosmiccal/astcosmiccal.conf b/bin/cosmiccal/astcosmiccal.conf
index 06d9fa88..1df8a9af 100644
--- a/bin/cosmiccal/astcosmiccal.conf
+++ b/bin/cosmiccal/astcosmiccal.conf
@@ -41,3 +41,6 @@
oradiation 0.0
# Output:
+
+# Spectral lines:
+ lineunit angstrom
diff --git a/bin/cosmiccal/cosmiccal.c b/bin/cosmiccal/cosmiccal.c
index b7a089a9..c8c8b8bb 100644
--- a/bin/cosmiccal/cosmiccal.c
+++ b/bin/cosmiccal/cosmiccal.c
@@ -203,19 +203,20 @@ cosmiccal(struct cosmiccalparams *p)
break;
case UI_KEY_ARCSECTANDIST:
- printf("%f", ( gal_cosmology_angular_distance(p->redshift, p->H0,
- p->olambda,
- p->omatter,
- p->oradiation)
- * 1000 * M_PI / 3600 / 180 ) );
+ printf("%f", ( gal_cosmology_angular_distance(p->redshift,
+ p->H0,
+ p->olambda,
+ p->omatter,
+ p->oradiation)
+ * 1000 * M_PI / 3600 / 180 ) );
break;
case UI_KEY_LUMINOSITYDIST:
printf("%f", gal_cosmology_luminosity_distance(p->redshift,
- p->H0,
- p->olambda,
- p->omatter,
- p->oradiation));
+ p->H0,
+ p->olambda,
+ p->omatter,
+ p->oradiation));
break;
case UI_KEY_DISTANCEMODULUS:
@@ -240,8 +241,8 @@ cosmiccal(struct cosmiccalparams *p)
case UI_KEY_LOOKBACKTIME:
curage=gal_cosmology_age(0.0f, p->H0, p->olambda, p->omatter,
p->oradiation);
- zage=gal_cosmology_age(p->redshift, p->H0, p->olambda,
p->omatter,
- p->oradiation);
+ zage=gal_cosmology_age(p->redshift, p->H0, p->olambda,
+ p->omatter, p->oradiation);
printf("%f", curage-zage);
break;
@@ -264,7 +265,8 @@ cosmiccal(struct cosmiccalparams *p)
break;
case UI_KEY_LINEATZ:
- printf("%g", gal_list_f64_pop(&p->specific_arg)*(1+p->redshift));
+ printf("%g", ( gal_list_f64_pop(&p->specific_arg)
+ * (1+p->redshift) * p->lineunitmultip) );
break;
default:
@@ -274,7 +276,8 @@ cosmiccal(struct cosmiccalparams *p)
PACKAGE_BUGREPORT, tmp->v);
}
- /* Only add a space-character if there are more results to print. */
+ /* Only add a space-character if there are more results to
+ print. */
if(tmp->next) printf(" ");
}
diff --git a/bin/cosmiccal/main.h b/bin/cosmiccal/main.h
index e36d4997..626de62e 100644
--- a/bin/cosmiccal/main.h
+++ b/bin/cosmiccal/main.h
@@ -59,6 +59,7 @@ struct cosmiccalparams
double oradiation; /* Current radiation density. */
uint8_t listlines; /* List the known spectral lines. */
uint8_t listlinesatz; /* List the known spectral lines. */
+ char * lineunit; /* Unit of numbers for lines. */
/* Outputs. */
gal_list_i32_t *specific; /* Codes for single row calculations. */
@@ -66,6 +67,8 @@ struct cosmiccalparams
/* Internal: */
time_t rawtime; /* Starting time of the program. */
+ double lineunitmultip; /* Multiple for using line units. */
+ uint8_t haslineatz; /* A flag for sanity checks. */
};
#endif
diff --git a/bin/cosmiccal/ui.c b/bin/cosmiccal/ui.c
index b665e085..40be5d6f 100644
--- a/bin/cosmiccal/ui.c
+++ b/bin/cosmiccal/ui.c
@@ -32,6 +32,7 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <gnuastro/fits.h>
#include <gnuastro/table.h>
+#include <gnuastro/pointer.h>
#include <gnuastro/speclines.h>
#include <gnuastro/cosmology.h>
@@ -206,6 +207,7 @@ ui_add_to_single_value(struct argp_option *option, char
*arg,
{
int linecode;
double *dptr, val=NAN;
+ gal_list_str_t *ltmp, *lines;
struct cosmiccalparams *p = (struct cosmiccalparams *)params;
/* In case of printing the option values. */
@@ -224,22 +226,36 @@ ui_add_to_single_value(struct argp_option *option, char
*arg,
{
/* Options with arguments. */
case UI_KEY_LINEATZ:
+
/* Make sure an argument is given. */
if(arg==NULL)
error(EXIT_FAILURE, 0, "option '--lineatz' needs an argument");
- /* If the argument is a number, read it, if not, see if its a known
- specral line name. */
- dptr=&val;
- if( gal_type_from_string((void **)(&dptr), arg, GAL_TYPE_FLOAT64) )
+ /* The input can be a coma-separated string. */
+ lines=gal_options_parse_csv_strings_to_list(arg, filename, lineno);
+ gal_list_str_reverse(&lines); /* the function returns the raw list. */
+ for(ltmp=lines;ltmp!=NULL;ltmp=ltmp->next)
{
- linecode=gal_speclines_line_code(arg);
- if(linecode==GAL_SPECLINES_INVALID)
- error(EXIT_FAILURE, 0, "'%s' not a known spectral line name",
- arg);
- val=gal_speclines_line_angstrom(linecode);
+ /* If the argument is a number, read it, if not, see if it is a
+ known specral line name. */
+ dptr=&val;
+ if( gal_type_from_string((void **)(&dptr), ltmp->v,
+ GAL_TYPE_FLOAT64) )
+ {
+ linecode=gal_speclines_line_code(ltmp->v);
+ if(linecode==GAL_SPECLINES_INVALID)
+ error(EXIT_FAILURE, 0, "'%s' not a known spectral line name",
+ ltmp->v);
+ val=gal_speclines_line_angstrom(linecode);
+ }
+ gal_list_f64_add(&p->specific_arg, val);
+
+ /* Add this option to the print list and return. */
+ gal_list_i32_add(option->value, option->key);
}
- gal_list_f64_add(&p->specific_arg, val);
+
+ /* Activate the flag for sanity checks later. */
+ p->haslineatz=1;
break;
/* Options without arguments. */
@@ -257,10 +273,10 @@ ui_add_to_single_value(struct argp_option *option, char
*arg,
/* Only proceed if the (possibly given) argument is 1. */
if(arg[0]=='0' && arg[1]=='\0') return NULL;
}
- }
- /* Add this option to the print list and return. */
- gal_list_i32_add(option->value, option->key);
+ /* Add this option to the print list and return. */
+ gal_list_i32_add(option->value, option->key);
+ }
return NULL;
}
@@ -392,10 +408,11 @@ ui_read_check_only_options(struct cosmiccalparams *p)
/* Check if the density fractions add up to 1 (within floating point
error). */
if( sum > (1+1e-8) || sum < (1-1e-8) )
- error(EXIT_FAILURE, 0, "sum of fractional densities is not 1, but %.8f. "
- "The cosmological constant ('olambda'), matter ('omatter') "
- "and radiation ('oradiation') densities are given as %.8f, %.8f, "
- "%.8f", sum, p->olambda, p->omatter, p->oradiation);
+ error(EXIT_FAILURE, 0, "sum of fractional densities is not 1, but "
+ "%.8f. The cosmological constant ('olambda'), matter "
+ "('omatter') and radiation ('oradiation') densities are given "
+ "as %.8f, %.8f, %.8f", sum, p->olambda, p->omatter,
+ p->oradiation);
/* Make sure that '--listlines' and '--listlinesatz' aren't called
together. */
@@ -403,6 +420,15 @@ ui_read_check_only_options(struct cosmiccalparams *p)
error(EXIT_FAILURE, 0, "'--listlines' and '--listlinesatz' can't be "
"called together");
+ /* If any of the line options are requested, make sure that 'lineunit' is
+ also given. */
+ if( (p->listlines || p->listlinesatz || p->haslineatz || hasobsline)
+ && p->lineunit==0 )
+ error(EXIT_FAILURE, 0, "no '--lineunit' specified! For the "
+ "operations on lines, it is necessary to specify the unit "
+ "of the reported wavelength with this option. See the output "
+ "of '--help' for acceptable values");
+
/* Make sure that '--redshift' and '--obsline' aren't called together. */
if( (hasredshift + hasvelocity + hasobsline) > 1 )
error(EXIT_FAILURE, 0, "only one of '--redshift', '--velocity', or "
@@ -434,30 +460,59 @@ ui_read_check_only_options(struct cosmiccalparams *p)
static void
ui_list_lines(struct cosmiccalparams *p)
{
- size_t i;
+ double ang;
+ size_t i, j;
+
+ /* Make sure '--lineunit' is given. */
+ if(p->lineunit==NULL)
+ error(EXIT_FAILURE, 0, "no unit specified for the wavelength of the "
+ "spectral lines. Please use '--lineunit' to specify your "
+ "desired unit");
/* Print basic information. Note that '--listlinesatz' is requested, also
print the redshift used. */
- printf("# %s\n", PROGRAM_STRING);
- if(p->listlinesatz)
- printf("# Assumed redshift: %g\n", p->redshift);
-
- /* Print column metadata. */
- printf("# Column 1: Wavelength [Angstrom,f32] %s.\n",
- ( p->listlinesatz
- ? "Line wavelength at assumed redshift"
- : "Rest frame wavelength of the line"));
- printf("# Column 2: Name [name, str10] Line name in Gnuastro.\n");
+ if(p->cp.quiet==0)
+ {
+ printf("# %s\n", PROGRAM_STRING);
+ if(p->listlinesatz)
+ printf("# Assumed redshift: %g\n", p->redshift);
+ printf("# Source of rest frame wavelenghts (retrieved on 2023-01-15):\n"
+ "# http://astronomy.nmsu.edu/drewski/tableofemission"
+ "lines.html\n");
+
+ /* Print column metadata. */
+ printf("# Column 1: Wavelength [%s,f32] %s.\n", p->lineunit,
+ ( p->listlinesatz
+ ? "Line wavelength at assumed redshift"
+ : "Rest frame wavelength of the line"));
+ printf("# Column 2: Name [name, str15] Line name in Gnuastro.\n");
+ }
/* Print the line information. */
- for(i=1;i<GAL_SPECLINES_INVALID_MAX;++i)
- printf("%-15g%s\n",
- ( p->listlinesatz
- ? ( gal_speclines_line_angstrom(i) * (1+p->redshift) )
- : gal_speclines_line_angstrom(i) ),
- gal_speclines_line_name(i));
-
- /* Abort the program. */
+ for(i=1;i<GAL_SPECLINES_NUMBER;++i)
+ {
+ /* Get the wavelength (in angstroms) for this line and print it. */
+ ang=gal_speclines_line_angstrom(i);
+ printf("%-20g%s\n",
+ ( p->listlinesatz
+ ? ( ang * (1+p->redshift) ) : ang ) * p->lineunitmultip,
+ gal_speclines_line_name(i));
+ }
+
+ /* Print the break locations. */
+ if(p->cp.quiet==0) printf("\n# Hydrogen series limits:\n");
+ for(i=0;i<GAL_SPECLINES_LIMIT_NUMBER;++i)
+ {
+ /* Get the wavelength (in angstroms) for this line and print it. */
+ j=i+GAL_SPECLINES_LIMIT_LYMAN;
+ ang=gal_speclines_line_angstrom(j);
+ printf("%-20g%s\n",
+ ( p->listlinesatz
+ ? ( ang * (1+p->redshift) ) : ang ) * p->lineunitmultip,
+ gal_speclines_line_name(j));
+ }
+
+ /* Abort the program successfully. */
exit(EXIT_SUCCESS);
}
@@ -465,6 +520,23 @@ ui_list_lines(struct cosmiccalparams *p)
+static void
+ui_preparations_lineunit(struct cosmiccalparams *p)
+{
+ if( !strcmp(p->lineunit, "m") ) p->lineunitmultip=1e-10;
+ else if( !strcmp(p->lineunit, "nano-m") ) p->lineunitmultip=0.1;
+ else if( !strcmp(p->lineunit, "micro-m") ) p->lineunitmultip=1e-4;
+ else if( !strcmp(p->lineunit, "angstrom") ) p->lineunitmultip=1;
+ else
+ error(EXIT_FAILURE, 0, "invalid value '%s' to '--lineunit'! Please "
+ "re-run this command with '--help' to see the acceptable "
+ "values", p->lineunit);
+}
+
+
+
+
+
static void
ui_preparations(struct cosmiccalparams *p)
{
@@ -481,20 +553,23 @@ ui_preparations(struct cosmiccalparams *p)
"'--redshift', '--velocity' (in km/s), or '--obsline' to specify "
"a redshift, run with '--help' for more");
+ /* If a line unit is given find the factor that should be multiplied. */
+ if(p->lineunit || p->obsline) ui_preparations_lineunit(p);
+
/* If '--listlines' is given, print them and abort the program
successfully, don't continue with the preparations. Note that
'--listlines' is the rest-frame lines. So we don't need any
redshift. */
- if(p->listlines)
- ui_list_lines(p);
+ if(p->listlines) ui_list_lines(p);
/* If '--obsline' has been given, set the redshift based on it (it can't
be called with '--velocity'). */
if(p->obsline)
p->redshift = ( (p->obsline->status==GAL_SPECLINES_INVALID)
? gal_speclines_line_redshift(obsline[0], obsline[1])
- : gal_speclines_line_redshift_code(obsline[0],
- p->obsline->status) );
+ : gal_speclines_line_redshift_code( (obsline[0]
+ / p->lineunitmultip),
+ p->obsline->status) );
/* If '--velocity' has been given, set the redshift based on it (it can't
be called with '--obsline'). */
@@ -507,10 +582,20 @@ ui_preparations(struct cosmiccalparams *p)
check.*/
if(p->redshift==0.0f) p->redshift=MAIN_REDSHIFT_ZERO;
+ /* In case the redshift is negative, print an error. It will be detected
+ and abort the program, prior to this if given directly, but can also
+ happen with '--obsline' for example). */
+ if(p->redshift<0)
+ error(EXIT_FAILURE, 0, "the selected redshift (%.4f) is negative! "
+ "This can happen when you give unreasonable values to indirect "
+ "ways of specifying the redshift. For example calling "
+ "'--obsline=H-alpha,2000'. When calling '--obsline', please "
+ "make sure that your observed line is redder than the rest-frame "
+ "wavelength of the given line", p->redshift);
+
/* Now that we have the redshift, we can print the 'listlinesatz'
option. */
- if(p->listlinesatz)
- ui_list_lines(p);
+ if(p->listlinesatz) ui_list_lines(p);
/* The list is filled out in a first-in-last-out order. By the time
control reaches here, the list is finalized. So we should just reverse
diff --git a/bin/cosmiccal/ui.h b/bin/cosmiccal/ui.h
index db92e7da..ac64dabe 100644
--- a/bin/cosmiccal/ui.h
+++ b/bin/cosmiccal/ui.h
@@ -75,7 +75,8 @@ enum option_keys_enum
/* Only with long version (start with a value 1000, the rest will be set
automatically). */
- UI_KEY_LISTLINES = 1000,
+ UI_KEY_LINEUNIT = 1000,
+ UI_KEY_LISTLINES,
UI_KEY_LISTLINESATZ,
};
diff --git a/bin/fits/ui.c b/bin/fits/ui.c
index 02c78070..463e0256 100644
--- a/bin/fits/ui.c
+++ b/bin/fits/ui.c
@@ -308,7 +308,7 @@ ui_check_copykeys(struct fitsparams *p)
{
if(p->copykeysrange[0]==GAL_BLANK_LONG)
{
- p->copykeysname=gal_options_parse_csv_strings_raw(pt,
+ p->copykeysname=gal_options_parse_csv_strings_to_data(pt,
NULL, 0);
break;
}
diff --git a/bin/match/ui.c b/bin/match/ui.c
index 73753c89..7c51a489 100644
--- a/bin/match/ui.c
+++ b/bin/match/ui.c
@@ -628,14 +628,15 @@ ui_set_columns_sanity_check_read_aperture(struct
matchparams *p)
if(p->coord || p->kdtreemode==MATCH_KDTREE_BUILD)
{
if(p->ccol1==NULL)
- error(EXIT_FAILURE, 0, "no value given to '--ccol1' (necessary with "
- "'--coord')");
+ error(EXIT_FAILURE, 0, "no value given to '--ccol1' (necessary "
+ "with '--coord')");
}
else
{
if(p->ccol1==NULL || p->ccol2==NULL)
- error(EXIT_FAILURE, 0, "both '--ccol1' and '--ccol2' must be given. "
- "They specify the columns containing the coordinates to match");
+ error(EXIT_FAILURE, 0, "both '--ccol1' and '--ccol2' must be "
+ "given. They specify the columns containing the "
+ "coordinates to match");
}
/* Make sure the same number of columns is given to both. Note that a
@@ -661,8 +662,8 @@ ui_set_columns_sanity_check_read_aperture(struct
matchparams *p)
{
case 1:
if(p->aperture->size>1)
- error(EXIT_FAILURE, 0, "%zu values given to '--aperture'. In a 1D "
- "match, this option can only take one value",
+ error(EXIT_FAILURE, 0, "%zu values given to '--aperture'. In "
+ "a 1D match, this option can only take one value",
p->aperture->size);
break;
diff --git a/bin/mkcatalog/args.h b/bin/mkcatalog/args.h
index 1db8293a..774b64c8 100644
--- a/bin/mkcatalog/args.h
+++ b/bin/mkcatalog/args.h
@@ -258,19 +258,6 @@ struct argp_option program_options[] =
GAL_OPTIONS_NOT_MANDATORY,
GAL_OPTIONS_NOT_SET
},
- {
- "spectrum",
- UI_KEY_SPECTRUM,
- 0,
- 0,
- "Object spectrum for cube (3D) datasets.",
- GAL_OPTIONS_GROUP_OUTPUT,
- &p->spectrum,
- GAL_OPTIONS_NO_ARG_TYPE,
- GAL_OPTIONS_RANGE_0_OR_1,
- GAL_OPTIONS_NOT_MANDATORY,
- GAL_OPTIONS_NOT_SET
- },
{
"inbetweenints",
UI_KEY_INBETWEENINTS,
@@ -2006,6 +1993,143 @@ struct argp_option program_options[] =
+
+ /* Multi-valued measurements. */
+ {
+ 0, 0, 0, 0,
+ "Vector (multi-valued) measurements",
+ UI_GROUP_COLUMNS_VECTOR
+ },
+ {
+ "sum-in-slice",
+ UI_KEY_SUMINSLICE,
+ 0,
+ 0,
+ "[3D input] Sum of values in each slice.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+ {
+ "sum-err-in-slice",
+ UI_KEY_SUMERRINSLICE,
+ 0,
+ 0,
+ "[3D input] Error in '--sum-in-slice'.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+ {
+ "area-in-slice",
+ UI_KEY_AREAINSLICE,
+ 0,
+ 0,
+ "[3D input] Number of labeled in each slice.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+ {
+ "sum-proj-in-slice",
+ UI_KEY_SUMPROJINSLICE,
+ 0,
+ 0,
+ "[3D input] Sum of projected area in each slice.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+ {
+ "area-proj-in-slice",
+ UI_KEY_AREAPROJINSLICE,
+ 0,
+ 0,
+ "[3D input] Num. voxels in '--sum-proj-in-slice'.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+ {
+ "sum-proj-err-in-slice",
+ UI_KEY_SUMPROJERRINSLICE,
+ 0,
+ 0,
+ "[3D input] Error of '--sum-proj-in-slice'.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+ {
+ "area-other-in-slice",
+ UI_KEY_AREAOTHERINSLICE,
+ 0,
+ 0,
+ "[3D input] Area of other lab. in projected area.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+ {
+ "sum-other-in-slice",
+ UI_KEY_SUMOTHERINSLICE,
+ 0,
+ 0,
+ "[3D input] Sum of other lab. in projected area.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+ {
+ "sum-other-err-in-slice",
+ UI_KEY_SUMOTHERERRINSLICE,
+ 0,
+ 0,
+ "[3D input] Area in '--sum-other-in-slice'.",
+ UI_GROUP_COLUMNS_VECTOR,
+ 0,
+ GAL_TYPE_INVALID,
+ GAL_OPTIONS_RANGE_ANY,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET,
+ ui_column_codes_ll
+ },
+
+
+
+
{0}
};
diff --git a/bin/mkcatalog/columns.c b/bin/mkcatalog/columns.c
index 4758ad33..f1086e15 100644
--- a/bin/mkcatalog/columns.c
+++ b/bin/mkcatalog/columns.c
@@ -331,9 +331,9 @@ columns_sanity_check(struct mkcatalogparams *p)
case UI_KEY_GEOW3:
case UI_KEY_CLUMPSW3:
case UI_KEY_CLUMPSGEOW3:
- error(EXIT_FAILURE, 0, "%s (hdu %s) is a 2D dataset, so columns "
- "relating to a third dimension cannot be requested",
- p->objectsfile, p->cp.hdu);
+ error(EXIT_FAILURE, 0, "%s (hdu %s) is a 2D dataset, so "
+ "columns relating to a third dimension cannot be "
+ "requested", p->objectsfile, p->cp.hdu);
}
break;
@@ -377,9 +377,9 @@ void
columns_define_alloc(struct mkcatalogparams *p)
{
gal_list_i32_t *colcode;
- size_t ndim=p->objects->ndim;
gal_list_str_t *strtmp, *noclumpimg=NULL;
int disp_fmt=0, disp_width=0, disp_precision=0;
+ size_t dsize[2], colndim, inndim=p->objects->ndim;
char *name=NULL, *unit=NULL, *ocomment=NULL, *ccomment=NULL;
uint8_t otype=GAL_TYPE_INVALID, ctype=GAL_TYPE_INVALID, *oiflag, *ciflag;
@@ -391,14 +391,22 @@ columns_define_alloc(struct mkcatalogparams *p)
smaller domain of raw measurements. So to avoid having to calculate
something multiple times, each parameter will flag the intermediate
parameters it requires in these arrays. */
- oiflag = p->oiflag = gal_pointer_allocate(GAL_TYPE_UINT8, OCOL_NUMCOLS, 1,
- __func__, "oiflag");
- ciflag = p->ciflag = gal_pointer_allocate(GAL_TYPE_UINT8, CCOL_NUMCOLS, 1,
- __func__, "ciflag");
+ oiflag = p->oiflag = gal_pointer_allocate(GAL_TYPE_UINT8, OCOL_NUMCOLS,
+ 1, __func__, "oiflag");
+ ciflag = p->ciflag = gal_pointer_allocate(GAL_TYPE_UINT8, CCOL_NUMCOLS,
+ 1, __func__, "ciflag");
/* Allocate the columns. */
for(colcode=p->columnids; colcode!=NULL; colcode=colcode->next)
{
+ /* Dimensions of output column. By default: most columns will be
+ single dimensional, the vector columns will update this. Also,
+ vector outputs will need 'dsize[1]'. But to avoid forgetting,
+ we'll set it to an absurd value to cause a crash if it is
+ forgotten. */
+ colndim=1;
+ dsize[1]=GAL_BLANK_SIZE_T;
+
/* Set the column-specific parameters, please follow the same order
as 'args.h'. IMPORTANT: we want the names to be the same as the
option names. Note that zero 'disp_' variables will be
@@ -486,7 +494,8 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_SB:
name = "SURFACE_BRIGHTNESS";
unit = "mag/arcsec^2";
- ocomment = "Surface brightness (magnitude of
brightness/area).";
+ ocomment = "Surface brightness (magnitude of "
+ "brightness/area).";
ccomment = ocomment;
otype = GAL_TYPE_FLOAT32;
ctype = GAL_TYPE_FLOAT32;
@@ -518,7 +527,8 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_AREAXY:
name = "AREAXY";
unit = "counter";
- ocomment = "Projected valued pixels in first two dimensions.";
+ ocomment = "Projected valued pixels in first two "
+ "dimensions.";
ccomment = ocomment;
otype = GAL_TYPE_INT32;
ctype = GAL_TYPE_INT32;
@@ -964,7 +974,7 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_GY ] = ciflag[ CCOL_GY ] = 1;
oiflag[ OCOL_SUMWHT ] = ciflag[ CCOL_SUMWHT ] = 1;
oiflag[ OCOL_NUMALL ] = ciflag[ CCOL_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
{
oiflag[ OCOL_VZ ] = ciflag[ CCOL_VZ ] = 1;
oiflag[ OCOL_GZ ] = ciflag[ CCOL_GZ ] = 1;
@@ -988,7 +998,7 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_GY ] = ciflag[ CCOL_GY ] = 1;
oiflag[ OCOL_SUMWHT ] = ciflag[ CCOL_SUMWHT ] = 1;
oiflag[ OCOL_NUMALL ] = ciflag[ CCOL_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
{
oiflag[ OCOL_VZ ] = ciflag[ CCOL_VZ ] = 1;
oiflag[ OCOL_GZ ] = ciflag[ CCOL_GZ ] = 1;
@@ -1030,7 +1040,7 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_GX ] = ciflag[ CCOL_GX ] = 1;
oiflag[ OCOL_GY ] = ciflag[ CCOL_GY ] = 1;
oiflag[ OCOL_NUMALL ] = ciflag[ CCOL_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
oiflag[ OCOL_GZ ] = ciflag[ CCOL_GZ ] = 1;
break;
@@ -1048,7 +1058,7 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_GX ] = ciflag[ CCOL_GX ] = 1;
oiflag[ OCOL_GY ] = ciflag[ CCOL_GY ] = 1;
oiflag[ OCOL_NUMALL ] = ciflag[ CCOL_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
oiflag[ OCOL_GZ ] = ciflag[ CCOL_GZ ] = 1;
break;
@@ -1086,7 +1096,7 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_C_GY ] = 1;
oiflag[ OCOL_C_SUMWHT ] = 1;
oiflag[ OCOL_C_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
{
oiflag[ OCOL_C_VZ ] = 1;
oiflag[ OCOL_C_GZ ] = 1;
@@ -1110,7 +1120,7 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_C_GY ] = 1;
oiflag[ OCOL_C_SUMWHT ] = 1;
oiflag[ OCOL_C_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
{
oiflag[ OCOL_C_VZ ] = 1;
oiflag[ OCOL_C_GZ ] = 1;
@@ -1130,19 +1140,20 @@ columns_define_alloc(struct mkcatalogparams *p)
columns_alloc_clumpsradec(p);
oiflag[ OCOL_C_VX ] = 1;
oiflag[ OCOL_C_VY ] = 1;
- oiflag[ OCOL_C_VZ ] = 1;
oiflag[ OCOL_C_GX ] = 1;
oiflag[ OCOL_C_GY ] = 1;
- oiflag[ OCOL_C_GZ ] = 1;
oiflag[ OCOL_C_SUMWHT ] = 1;
oiflag[ OCOL_C_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
{
+ oiflag[ OCOL_C_VZ ] = 1;
+ oiflag[ OCOL_C_GZ ] = 1;
}
break;
case UI_KEY_CLUMPSGEOW1:
- name = gal_checkset_malloc_cat("CLUMPS_GEO", p->ctype[0]);
+ name = gal_checkset_malloc_cat("CLUMPS_GEO",
+ p->ctype[0]);
unit = p->objects->wcs->cunit[0];
ocomment = "Geometric center of all clumps (WCS axis 1).";
ccomment = NULL;
@@ -1155,12 +1166,13 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_C_GX ] = 1;
oiflag[ OCOL_C_GY ] = 1;
oiflag[ OCOL_C_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
oiflag[ OCOL_C_GZ ] = 1;
break;
case UI_KEY_CLUMPSGEOW2:
- name = gal_checkset_malloc_cat("CLUMPS_GEO", p->ctype[1]);
+ name = gal_checkset_malloc_cat("CLUMPS_GEO",
+ p->ctype[1]);
unit = p->objects->wcs->cunit[1];
ocomment = "Geometric center of all clumps (WCS axis 2).";
ccomment = NULL;
@@ -1173,12 +1185,13 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_C_GX ] = 1;
oiflag[ OCOL_C_GY ] = 1;
oiflag[ OCOL_C_NUMALL ] = 1;
- if(ndim==3)
+ if(inndim==3)
oiflag[ OCOL_C_GZ ] = 1;
break;
case UI_KEY_CLUMPSGEOW3:
- name = gal_checkset_malloc_cat("CLUMPS_GEO", p->ctype[2]);
+ name = gal_checkset_malloc_cat("CLUMPS_GEO",
+ p->ctype[2]);
unit = p->objects->wcs->cunit[2];
ocomment = "Geometric center of all clumps (WCS axis 3).";
ccomment = NULL;
@@ -1275,7 +1288,8 @@ columns_define_alloc(struct mkcatalogparams *p)
name = "STD";
unit = MKCATALOG_NO_UNIT;
ocomment = "Standard deviation of sky subtracted values.";
- ccomment = "Standard deviation of pixels subtracted by
rivers.";
+ ccomment = "Standard deviation of pixels subtracted by "
+ "rivers.";
otype = GAL_TYPE_FLOAT32;
ctype = GAL_TYPE_FLOAT32;
disp_fmt = GAL_TABLE_DISPLAY_FMT_GENERAL;
@@ -1367,8 +1381,10 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_SIGCLIPSTD:
name = "SIGCLIP-STD";
unit = MKCATALOG_NO_UNIT;
- ocomment = "Sigma-clipped standard deviation of object
pixels.";
- ccomment = "Sigma-clipped standard deviation of clump pixels.";
+ ocomment = "Sigma-clipped standard deviation of object "
+ "pixels.";
+ ccomment = "Sigma-clipped standard deviation of clump "
+ "pixels.";
otype = GAL_TYPE_FLOAT32;
ctype = GAL_TYPE_FLOAT32;
disp_fmt = GAL_TABLE_DISPLAY_FMT_GENERAL;
@@ -1515,7 +1531,8 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_UPPERLIMITSB:
name = "UPPERLIMIT_SB";
unit = "mag/arcsec^2";
- ocomment = "Upper limit surface brightness over its
footprint.";
+ ocomment = "Upper limit surface brightness over its "
+ "footprint.";
ccomment = ocomment;
otype = GAL_TYPE_FLOAT32;
ctype = GAL_TYPE_FLOAT32;
@@ -1586,7 +1603,7 @@ columns_define_alloc(struct mkcatalogparams *p)
disp_width = 8;
disp_precision = 3;
p->upperlimit = 1;
- oiflag[ OCOL_UPPERLIMIT_SKEW ] = oiflag[ CCOL_UPPERLIMIT_SKEW ] = 1;
+ oiflag[ OCOL_UPPERLIMIT_SKEW ]=oiflag[ CCOL_UPPERLIMIT_SKEW ]=1;
break;
case UI_KEY_RIVERMEAN:
@@ -1834,7 +1851,8 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_HALFSUMAREA:
name = "HALF_SUM_AREA";
unit = "counter";
- ocomment = "Number of brightest pixels containing half of
total sum.";
+ ocomment = "Number of brightest pixels containing half "
+ "of total sum.";
ccomment = ocomment;
otype = GAL_TYPE_INT32;
ctype = GAL_TYPE_INT32;
@@ -1849,7 +1867,8 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_HALFMAXAREA:
name = "HALF_MAX_AREA";
unit = "counter";
- ocomment = "Number of pixels with a value larger than half the
maximum.";
+ ocomment = "Number of pixels with a value larger than "
+ "half the maximum.";
ccomment = ocomment;
otype = GAL_TYPE_INT32;
ctype = GAL_TYPE_INT32;
@@ -1863,7 +1882,8 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_HALFMAXSUM:
name = "HALF_MAX_SUM";
unit = MKCATALOG_NO_UNIT;
- ocomment = "Sum of pixels with a value larger than half the
maximum.";
+ ocomment = "Sum of pixels with a value larger than half "
+ "the maximum.";
ccomment = ocomment;
otype = GAL_TYPE_FLOAT32;
ctype = GAL_TYPE_FLOAT32;
@@ -1877,7 +1897,8 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_HALFMAXSB:
name = "HALF_MAX_SB";
unit = "mag/arcsec^2";
- ocomment = "Surface brightness for pixels above half the
maximum.";
+ ocomment = "Surface brightness for pixels above half "
+ "the maximum.";
ccomment = ocomment;
otype = GAL_TYPE_FLOAT32;
ctype = GAL_TYPE_FLOAT32;
@@ -1892,7 +1913,8 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_HALFSUMSB:
name = "HALF_SUM_SB";
unit = "mag/arcsec^2";
- ocomment = "Surface brightness for pixels above half the sum
of all labeled pixels.";
+ ocomment = "Surface brightness for pixels above half "
+ "the sum of all labeled pixels.";
ccomment = ocomment;
otype = GAL_TYPE_FLOAT32;
ctype = GAL_TYPE_FLOAT32;
@@ -1919,12 +1941,14 @@ columns_define_alloc(struct mkcatalogparams *p)
oiflag[ OCOL_SUM ] = ciflag[ CCOL_SUM ] = 1;
if(colcode->v==UI_KEY_FRACMAX1SUM)
{
- ocomment = "Sum of pixels brighter than 1st fraction of
maximum.";
+ ocomment = "Sum of pixels brighter than 1st fraction of "
+ "maximum.";
oiflag[ OCOL_FRACMAX1SUM ] = ciflag[ CCOL_FRACMAX1SUM ] = 1;
}
else
{
- ocomment = "Sum of pixels brighter than 2nd fraction of
maximum.";
+ ocomment = "Sum of pixels brighter than 2nd fraction of "
+ "maximum.";
oiflag[ OCOL_FRACMAX2SUM ] = ciflag[ CCOL_FRACMAX2SUM ] = 1;
}
ccomment = ocomment;
@@ -1936,7 +1960,8 @@ columns_define_alloc(struct mkcatalogparams *p)
? "FRAC_MAX1_AREA"
: "FRAC_MAX2_AREA" );
unit = "counter";
- ocomment = "Number of pixels brighter than given fraction of
maximum value.";
+ ocomment = "Number of pixels brighter than given fraction "
+ "of maximum value.";
ccomment = ocomment;
otype = GAL_TYPE_INT32;
ctype = GAL_TYPE_INT32;
@@ -1962,9 +1987,11 @@ columns_define_alloc(struct mkcatalogparams *p)
disp_fmt = GAL_TABLE_DISPLAY_FMT_GENERAL;
disp_width = 10;
disp_precision = 3;
- oiflag[ OCOL_NUM ] = ciflag[ CCOL_NUM ] = 1; /*
halfsumarea */
+ /* halfsumarea: */
+ oiflag[ OCOL_NUM ] = ciflag[ CCOL_NUM ] = 1;
oiflag[ OCOL_SUM ] = ciflag[ CCOL_SUM ] = 1;
- oiflag[ OCOL_SUMWHT ] = ciflag[ CCOL_SUMWHT ] = 1; /*
axisratio. */
+ /* axisratio: */
+ oiflag[ OCOL_SUMWHT ] = ciflag[ CCOL_SUMWHT ] = 1;
oiflag[ OCOL_VX ] = ciflag[ CCOL_VX ] = 1;
oiflag[ OCOL_VY ] = ciflag[ CCOL_VY ] = 1;
oiflag[ OCOL_VXX ] = ciflag[ CCOL_VXX ] = 1;
@@ -1981,46 +2008,199 @@ columns_define_alloc(struct mkcatalogparams *p)
case UI_KEY_FWHM:
name="FWHM";
oiflag[ OCOL_HALFMAXNUM ] = ciflag[ CCOL_HALFMAXNUM ] = 1;
- ocomment = "Full width at half maximum (accounting for
ellipticity).";
+ ocomment = "Full width at half maximum (accounting for "
+ "ellipticity).";
break;
case UI_KEY_HALFMAXRADIUS:
name="HALF_MAX_RADIUS";
oiflag[ OCOL_HALFMAXNUM ] = ciflag[ CCOL_HALFMAXNUM ] = 1;
- ocomment = "Radius at half of maximum (accounting for
ellipticity).";
+ ocomment = "Radius at half of maximum (accounting for "
+ "ellipticity).";
break;
case UI_KEY_HALFSUMRADIUS:
name="HALF_SUM_RADIUS";
oiflag[ OCOL_HALFSUMNUM ] = ciflag[ CCOL_HALFSUMNUM ] = 1;
- ocomment = "Radius at half of total sum (accounting for
ellipticity).";
+ ocomment = "Radius at half of total sum (accounting for "
+ "ellipticity).";
break;
case UI_KEY_FRACMAX1RADIUS:
name="FRAC_MAX_RADIUS_1";
oiflag[ OCOL_FRACMAX1NUM ] = ciflag[ CCOL_FRACMAX1NUM ] = 1;
- ocomment = "Radius derived from area of 1st fraction of
maximum.";
+ ocomment = "Radius derived from area of 1st fraction of "
+ "maximum.";
break;
case UI_KEY_FRACMAX2RADIUS:
name="FRAC_MAX_RADIUS_2";
oiflag[ OCOL_FRACMAX2NUM ] = ciflag[ CCOL_FRACMAX2NUM ] = 1;
- ocomment = "Radius derived from area of 2nd fraction of
maximum.";
+ ocomment = "Radius derived from area of 2nd fraction of "
+ "maximum.";
break;
}
ccomment = ocomment;
break;
+ case UI_KEY_SUMINSLICE:
+ colndim = 2;
+ name = "SUM-IN-SLICE";
+ unit = MKCATALOG_NO_UNIT;
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Sum of values with this label in each slice.";
+ ccomment = ocomment;
+ otype = GAL_TYPE_FLOAT32;
+ ctype = GAL_TYPE_FLOAT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_SUMINSLICE ] = 1;
+ oiflag[ OCOL_NUMINSLICE ] = 1;
+ break;
+
+ case UI_KEY_SUMERRINSLICE:
+ colndim = 2;
+ name = "SUM-ERR-IN-SLICE";
+ unit = MKCATALOG_NO_UNIT;
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Error in 'SUM-IN-SLICE'";
+ ccomment = ocomment;
+ otype = GAL_TYPE_FLOAT32;
+ ctype = GAL_TYPE_FLOAT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_SUMINSLICE ] = 1;
+ oiflag[ OCOL_NUMINSLICE ] = 1;
+ oiflag[ OCOL_SUMVARINSLICE ] = 1;
+ break;
+
+ case UI_KEY_AREAINSLICE:
+ colndim = 2;
+ name = "AREA-IN-SLICE";
+ unit = "counter";
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Number of pixels of each label in each slice.";
+ ccomment = ocomment;
+ otype = GAL_TYPE_INT32;
+ ctype = GAL_TYPE_INT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_NUMINSLICE ] = 1;
+ break;
+
+ case UI_KEY_SUMPROJINSLICE:
+ colndim = 2;
+ name = "SUM-PROJ-IN-SLICE";
+ unit = MKCATALOG_NO_UNIT;
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Sum of values in projected area of each slice.";
+ ccomment = ocomment;
+ otype = GAL_TYPE_FLOAT32;
+ ctype = GAL_TYPE_FLOAT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_SUMPROJINSLICE ] = 1;
+ oiflag[ OCOL_NUMPROJINSLICE ] = 1;
+ break;
+
+ case UI_KEY_SUMPROJERRINSLICE:
+ colndim = 2;
+ name = "SUM-PROJ-ERR-IN-SLICE";
+ unit = MKCATALOG_NO_UNIT;
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Error in 'SUM-PROJ-IN-SLICE'";
+ ccomment = ocomment;
+ otype = GAL_TYPE_FLOAT32;
+ ctype = GAL_TYPE_FLOAT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_SUMPROJINSLICE ] = 1;
+ oiflag[ OCOL_NUMPROJINSLICE ] = 1;
+ oiflag[ OCOL_SUMPROJVARINSLICE ] = 1;
+ break;
+
+ case UI_KEY_AREAPROJINSLICE:
+ colndim = 2;
+ name = "AREA-PROJ-IN-SLICE";
+ unit = "counter";
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Number of usable pixels in "
+ "'SUM-PROJ-IN-SLICE'.";
+ ccomment = ocomment;
+ otype = GAL_TYPE_INT32;
+ ctype = GAL_TYPE_INT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_NUMPROJINSLICE ] = 1;
+ break;
+
+ case UI_KEY_SUMOTHERINSLICE:
+ colndim = 2;
+ name = "SUM-OTHER-IN-SLICE";
+ unit = MKCATALOG_NO_UNIT;
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Sum in other labels in projection in each "
+ "slice.";
+ ccomment = ocomment;
+ otype = GAL_TYPE_FLOAT32;
+ ctype = GAL_TYPE_FLOAT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_SUMOTHERINSLICE ] = 1;
+ oiflag[ OCOL_NUMOTHERINSLICE ] = 1;
+ break;
+
+ case UI_KEY_SUMOTHERERRINSLICE:
+ colndim = 2;
+ name = "SUM-OTHER-ERR-IN-SLICE";
+ unit = MKCATALOG_NO_UNIT;
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Error in 'SUM-OTHER-IN-SLICE'";
+ ccomment = ocomment;
+ otype = GAL_TYPE_FLOAT32;
+ ctype = GAL_TYPE_FLOAT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_SUMOTHERINSLICE ] = 1;
+ oiflag[ OCOL_NUMOTHERINSLICE ] = 1;
+ oiflag[ OCOL_SUMOTHERVARINSLICE ] = 1;
+ break;
+
+ case UI_KEY_AREAOTHERINSLICE:
+ colndim = 2;
+ name = "AREA-OTHER-IN-SLICE";
+ unit = "counter";
+ dsize[1] = p->objects->dsize[0]; /* Third FITS dim. */
+ ocomment = "Number of usable pixels in "
+ "'SUM-OTHER-IN-SLICE'";
+ ccomment = ocomment;
+ otype = GAL_TYPE_INT32;
+ ctype = GAL_TYPE_INT32;
+ disp_fmt = 0;
+ disp_width = 6;
+ disp_precision = 0;
+ oiflag[ OCOL_NUMOTHERINSLICE ] = 1;
+ break;
+
default:
- error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s to fix "
- "the problem. The code %d is not an internally recognized "
- "column code", __func__, PACKAGE_BUGREPORT, colcode->v);
+ error(EXIT_FAILURE, 0, "%s: a bug! please contact us at %s to "
+ "fix the problem. The code %d is not an internally "
+ "recognized column code", __func__, PACKAGE_BUGREPORT,
+ colcode->v);
}
-
/* If this is an object's column, add it to the list of columns. We
will be using the 'status' element to keep the MakeCatalog code
for the columns. */
if(otype!=GAL_TYPE_INVALID)
{
- gal_list_data_add_alloc(&p->objectcols, NULL, otype, 1,
- &p->numobjects, NULL, 0, p->cp.minmapsize,
+ dsize[0]=p->numobjects;
+ gal_list_data_add_alloc(&p->objectcols, NULL, otype, colndim,
+ dsize, NULL, 0, p->cp.minmapsize,
p->cp.quietmmap, name, unit, ocomment);
p->objectcols->status = colcode->v;
p->objectcols->disp_fmt = disp_fmt;
@@ -2028,7 +2208,6 @@ columns_define_alloc(struct mkcatalogparams *p)
p->objectcols->disp_precision = disp_precision;
}
-
/* Similar to the objects column above but for clumps, but since the
clumps image is optional, we need a further check before actually
allocating the column. */
@@ -2037,10 +2216,11 @@ columns_define_alloc(struct mkcatalogparams *p)
/* If a clumps labeled image, add this column for the output. */
if(p->clumps)
{
- gal_list_data_add_alloc(&p->clumpcols, NULL, ctype, 1,
- &p->numclumps, NULL, 0,
- p->cp.minmapsize, p->cp.quietmmap,
- name, unit, ccomment);
+ dsize[0]=p->numclumps;
+ gal_list_data_add_alloc(&p->clumpcols, NULL, ctype, colndim,
+ dsize, NULL, 0, p->cp.minmapsize,
+ p->cp.quietmmap, name, unit,
+ ccomment);
p->clumpcols->status = colcode->v;
p->clumpcols->disp_fmt = disp_fmt;
p->clumpcols->disp_width = disp_width;
@@ -2072,10 +2252,10 @@ columns_define_alloc(struct mkcatalogparams *p)
{
gal_list_str_reverse(&noclumpimg);
fprintf(stderr, "WARNING: the following column(s) are unique to "
- "clumps (not objects), but the '--clumpscat' option has not "
- "been called, or there were no clumps in the clumps labeled "
- "image. Hence, these columns will be ignored in the "
- "output.\n\n");
+ "clumps (not objects), but the '--clumpscat' option has "
+ "not been called, or there were no clumps in the clumps "
+ "labeled image. Hence, these columns will be ignored in "
+ "the output.\n\n");
for(strtmp=noclumpimg; strtmp!=NULL; strtmp=strtmp->next)
fprintf(stderr, "\t%s\n", strtmp->v);
gal_list_str_free(noclumpimg, 1);
@@ -2113,8 +2293,8 @@ columns_define_alloc(struct mkcatalogparams *p)
/******************************************************************/
#define MKC_RATIO(TOP,BOT) ( (BOT)!=0.0f ? (TOP)/(BOT) : NAN )
#define MKC_MAG(B) ( gal_units_counts_to_mag(B, p->zeropoint) )
-#define MKC_SB(B, A) ( ((B)>0 && (A)>0) \
- ? MKC_MAG(B) + 2.5f * log10((A) * p->pixelarcsecsq) \
+#define MKC_SB(B, A) ( ((B)>0 && (A)>0) \
+ ? MKC_MAG(B) + 2.5f * log10((A)*p->pixelarcsecsq) \
: NAN )
@@ -2221,9 +2401,9 @@ columns_second_order(struct mkcatalog_passparams *pp,
double *row,
/* Error. */
default:
- error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
- "problem. %d is not a recognized key", __func__, PACKAGE_BUGREPORT,
- key);
+ error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix "
+ "the problem. %d is not a recognized key", __func__,
+ PACKAGE_BUGREPORT, key);
}
/* Return the output. */
@@ -2311,14 +2491,13 @@ columns_xy_extrema(struct mkcatalog_passparams *pp,
double *oi,
case UI_KEY_MINZ: return coord[ndim-3] + 1; break;
case UI_KEY_MAXZ: return coord[ndim-3] + tile->dsize[ndim-3]; break;
default:
- error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to fix the "
- "problem. The value %d is not a recognized value", __func__,
- PACKAGE_BUGREPORT, key);
+ error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to "
+ "fix the problem. The value %d is not a recognized value",
+ __func__, PACKAGE_BUGREPORT, key);
}
else
return 0;
-
/* 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",
@@ -2330,6 +2509,73 @@ columns_xy_extrema(struct mkcatalog_passparams *pp,
double *oi,
+/* Fill vector columns. */
+static void
+columns_vector_fill(int key, gal_data_t *column, gal_data_t *v,
+ size_t oind)
+{
+ int sqr=0;
+ float *of32;
+ int32_t *oi32;
+ gal_data_t *vec;
+ int32_t *ii32, *ii32f;
+ double *if64, *if64f;
+
+ /* Set the input pointer. */
+ switch(key)
+ {
+ case UI_KEY_SUMINSLICE: vec=&v[VEC_SUMINSLICE]; break;
+ case UI_KEY_AREAINSLICE: vec=&v[VEC_NUMINSLICE]; break;
+ case UI_KEY_SUMPROJINSLICE: vec=&v[VEC_SUMPROJINSLICE]; break;
+ case UI_KEY_AREAPROJINSLICE: vec=&v[VEC_NUMPROJINSLICE]; break;
+ case UI_KEY_AREAOTHERINSLICE: vec=&v[VEC_NUMOTHERINSLICE]; break;
+ case UI_KEY_SUMOTHERINSLICE: vec=&v[VEC_SUMOTHERINSLICE]; break;
+
+ /* Those that need special attention. */
+ case UI_KEY_SUMERRINSLICE:
+ vec=&v[VEC_SUMVARINSLICE]; sqr=1; break;
+ case UI_KEY_SUMPROJERRINSLICE:
+ vec=&v[VEC_SUMPROJVARINSLICE]; sqr=1; break;
+ case UI_KEY_SUMOTHERERRINSLICE:
+ vec=&v[VEC_SUMOTHERVARINSLICE]; sqr=1; break;
+
+ /* Unexpected! */
+ default:
+ error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at '%s' to "
+ "fix the problem. Column identifier '%d' is not expected "
+ "here", __func__, PACKAGE_BUGREPORT, key);
+ }
+
+ /* Set the pointers. */
+ ii32 = vec->array; ii32f = ii32 + vec->size;
+ if64 = vec->array; if64f = if64 + vec->size;
+
+ /* Copy the values, one by one.*/
+ switch(column->type)
+ {
+ case GAL_TYPE_INT32:
+ oi32=gal_pointer_increment(column->array, oind*column->dsize[1],
+ column->type);
+ if(sqr) {do *oi32++ = sqrt(*ii32); while(++ii32<ii32f);}
+ else {do *oi32++ = *ii32; while(++ii32<ii32f);}
+ break;
+
+ case GAL_TYPE_FLOAT32:
+ of32=gal_pointer_increment(column->array, oind*column->dsize[1],
+ column->type);
+ do *of32++ = *if64; while(++if64<if64f);
+ break;
+
+ default:
+ error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at '%s' to "
+ "fix the problem. Output type '%s' is not expected",
+ __func__, PACKAGE_BUGREPORT, gal_type_name(column->type, 1));
+ }
+}
+
+
+
+
/* The magnitude error is directly derivable from the S/N:
To derive the error in measuring the magnitude from the S/N, let's take
@@ -2387,13 +2633,12 @@ columns_fill(struct mkcatalog_passparams *pp)
int key;
double tmp;
void *colarr;
- gal_data_t *column;
- double *ci, *oi=pp->oi;
size_t tmpind=GAL_BLANK_SIZE_T;
- size_t coord[3]={GAL_BLANK_SIZE_T, GAL_BLANK_SIZE_T, GAL_BLANK_SIZE_T};
-
+ gal_data_t *column, *vec=pp->vector;
+ double *ci, *oi=pp->oi, **vcc=NULL, **gcc=NULL;
+ double **vo=NULL, **vc=NULL, **go=NULL, **gc=NULL;
size_t i, cind, coind, sr=pp->clumpstartindex, oind=GAL_BLANK_SIZE_T;
- double **vo=NULL, **vc=NULL, **go=NULL, **gc=NULL, **vcc=NULL, **gcc=NULL;
+ size_t coord[3]={GAL_BLANK_SIZE_T, GAL_BLANK_SIZE_T, GAL_BLANK_SIZE_T};
/* Find the object's index in final catalog. */
if(p->outlabs)
@@ -2483,30 +2728,36 @@ columns_fill(struct mkcatalog_passparams *pp)
break;
case UI_KEY_GEOX:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_GX], oi[OCOL_NUMALL] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_GX],
+ oi[OCOL_NUMALL] );
break;
case UI_KEY_GEOY:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_GY], oi[OCOL_NUMALL] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_GY],
+ oi[OCOL_NUMALL] );
break;
case UI_KEY_GEOZ:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_GZ], oi[OCOL_NUMALL] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_GZ],
+ oi[OCOL_NUMALL] );
break;
case UI_KEY_CLUMPSX:
- ((float *)colarr)[oind] = POS_V_G(oi, OCOL_C_SUMWHT, OCOL_C_NUMWHT,
- OCOL_C_VX, OCOL_C_GX);
+ ((float *)colarr)[oind] = POS_V_G(oi, OCOL_C_SUMWHT,
+ OCOL_C_NUMWHT, OCOL_C_VX,
+ OCOL_C_GX);
break;
case UI_KEY_CLUMPSY:
- ((float *)colarr)[oind] = POS_V_G(oi, OCOL_C_SUMWHT, OCOL_C_NUMWHT,
- OCOL_C_VY, OCOL_C_GY);
+ ((float *)colarr)[oind] = POS_V_G(oi, OCOL_C_SUMWHT,
+ OCOL_C_NUMWHT, OCOL_C_VY,
+ OCOL_C_GY);
break;
case UI_KEY_CLUMPSZ:
- ((float *)colarr)[oind] = POS_V_G(oi, OCOL_C_SUMWHT, OCOL_C_NUMALL,
- OCOL_C_VZ, OCOL_C_GZ);
+ ((float *)colarr)[oind] = POS_V_G(oi, OCOL_C_SUMWHT,
+ OCOL_C_NUMALL, OCOL_C_VZ,
+ OCOL_C_GZ);
break;
case UI_KEY_CLUMPSGEOX:
@@ -2525,27 +2776,33 @@ columns_fill(struct mkcatalog_passparams *pp)
break;
case UI_KEY_MINVALX:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MINVX],
oi[OCOL_MINVNUM] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MINVX],
+ oi[OCOL_MINVNUM] );
break;
case UI_KEY_MAXVALX:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MAXVX],
oi[OCOL_MAXVNUM] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MAXVX],
+ oi[OCOL_MAXVNUM] );
break;
case UI_KEY_MINVALY:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MINVY],
oi[OCOL_MINVNUM] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MINVY],
+ oi[OCOL_MINVNUM] );
break;
case UI_KEY_MAXVALY:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MAXVY],
oi[OCOL_MAXVNUM] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MAXVY],
+ oi[OCOL_MAXVNUM] );
break;
case UI_KEY_MINVALZ:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MINVZ],
oi[OCOL_MINVNUM] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MINVZ],
+ oi[OCOL_MINVNUM] );
break;
case UI_KEY_MAXVALZ:
- ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MAXVZ],
oi[OCOL_MAXVNUM] );
+ ((float *)colarr)[oind] = MKC_RATIO( oi[OCOL_MAXVZ],
+ oi[OCOL_MAXVNUM] );
break;
case UI_KEY_MINVALNUM:
@@ -2562,7 +2819,8 @@ columns_fill(struct mkcatalog_passparams *pp)
case UI_KEY_MAXY:
case UI_KEY_MINZ:
case UI_KEY_MAXZ:
- ((uint32_t *)colarr)[oind]=columns_xy_extrema(pp, oi, coord, key);
+ ((uint32_t *)colarr)[oind]=columns_xy_extrema(pp, oi, coord,
+ key);
break;
case UI_KEY_W1:
@@ -2589,10 +2847,10 @@ columns_fill(struct mkcatalog_passparams *pp)
case UI_KEY_CLUMPSW1:
case UI_KEY_CLUMPSW2:
case UI_KEY_CLUMPSW3:
- vcc[0][oind] = POS_V_G(oi, OCOL_C_SUMWHT, OCOL_C_NUMALL, OCOL_C_VX,
- OCOL_C_GX);
- vcc[1][oind] = POS_V_G(oi, OCOL_C_SUMWHT, OCOL_C_NUMALL, OCOL_C_VY,
- OCOL_C_GY);
+ vcc[0][oind] = POS_V_G(oi, OCOL_C_SUMWHT, OCOL_C_NUMALL,
+ OCOL_C_VX, OCOL_C_GX);
+ vcc[1][oind] = POS_V_G(oi, OCOL_C_SUMWHT, OCOL_C_NUMALL,
+ OCOL_C_VY, OCOL_C_GY);
if(p->objects->ndim==3)
vcc[2][oind] = POS_V_G(oi, OCOL_C_SUMWHT, OCOL_C_NUMALL,
OCOL_C_VZ, OCOL_C_GZ);
@@ -2724,7 +2982,8 @@ columns_fill(struct mkcatalog_passparams *pp)
break;
case UI_KEY_SKY:
- ((float *)colarr)[oind] = MKC_RATIO(oi[OCOL_SUMSKY],
oi[OCOL_NUMSKY]);
+ ((float *)colarr)[oind] = MKC_RATIO(oi[OCOL_SUMSKY],
+ oi[OCOL_NUMSKY]);
break;
case UI_KEY_SKYSTD:
@@ -2830,10 +3089,23 @@ columns_fill(struct mkcatalog_passparams *pp)
((float *)colarr)[oind] = tmp<1e-6 ? NAN : tmp;
break;
+ case UI_KEY_SUMINSLICE:
+ case UI_KEY_AREAINSLICE:
+ case UI_KEY_SUMERRINSLICE:
+ case UI_KEY_SUMPROJINSLICE:
+ case UI_KEY_AREAPROJINSLICE:
+ case UI_KEY_SUMOTHERINSLICE:
+ case UI_KEY_AREAOTHERINSLICE:
+ case UI_KEY_SUMPROJERRINSLICE:
+ case UI_KEY_SUMOTHERERRINSLICE:
+ columns_vector_fill(key, column, vec, oind);
+ break;
+
default:
error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to "
- "solve the problem. the output column code %d not recognized "
- "(for objects). ", __func__, PACKAGE_BUGREPORT, key);
+ "solve the problem. the output column code %d not "
+ "recognized (for objects). ", __func__, PACKAGE_BUGREPORT,
+ key);
}
}
@@ -2927,27 +3199,33 @@ columns_fill(struct mkcatalog_passparams *pp)
break;
case UI_KEY_MINVALX:
- ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MINVX],
ci[CCOL_MINVNUM] );
+ ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MINVX],
+ ci[CCOL_MINVNUM] );
break;
case UI_KEY_MAXVALX:
- ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MAXVX],
ci[CCOL_MAXVNUM] );
+ ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MAXVX],
+ ci[CCOL_MAXVNUM] );
break;
case UI_KEY_MINVALY:
- ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MINVY],
ci[CCOL_MINVNUM] );
+ ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MINVY],
+ ci[CCOL_MINVNUM] );
break;
case UI_KEY_MAXVALY:
- ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MAXVY],
ci[CCOL_MAXVNUM] );
+ ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MAXVY],
+ ci[CCOL_MAXVNUM] );
break;
case UI_KEY_MINVALZ:
- ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MINVZ],
ci[CCOL_MINVNUM] );
+ ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MINVZ],
+ ci[CCOL_MINVNUM] );
break;
case UI_KEY_MAXVALZ:
- ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MAXVZ],
ci[CCOL_MAXVNUM] );
+ ((float *)colarr)[cind] = MKC_RATIO( ci[CCOL_MAXVZ],
+ ci[CCOL_MAXVNUM] );
break;
case UI_KEY_MINVALNUM:
@@ -2958,12 +3236,12 @@ columns_fill(struct mkcatalog_passparams *pp)
((uint32_t *)colarr)[cind] = ci[CCOL_MAXVNUM];
break;
- case UI_KEY_MINX: ((uint32_t *)colarr)[cind] = ci[CCOL_MINX];
break;
- case UI_KEY_MAXX: ((uint32_t *)colarr)[cind] = ci[CCOL_MAXX];
break;
- case UI_KEY_MINY: ((uint32_t *)colarr)[cind] = ci[CCOL_MINY];
break;
- case UI_KEY_MAXY: ((uint32_t *)colarr)[cind] = ci[CCOL_MAXY];
break;
- case UI_KEY_MINZ: ((uint32_t *)colarr)[cind] = ci[CCOL_MINZ];
break;
- case UI_KEY_MAXZ: ((uint32_t *)colarr)[cind] = ci[CCOL_MAXZ];
break;
+ case UI_KEY_MINX: ((uint32_t *)colarr)[cind]=ci[CCOL_MINX];break;
+ case UI_KEY_MAXX: ((uint32_t *)colarr)[cind]=ci[CCOL_MAXX];break;
+ case UI_KEY_MINY: ((uint32_t *)colarr)[cind]=ci[CCOL_MINY];break;
+ case UI_KEY_MAXY: ((uint32_t *)colarr)[cind]=ci[CCOL_MAXY];break;
+ case UI_KEY_MINZ: ((uint32_t *)colarr)[cind]=ci[CCOL_MINZ];break;
+ case UI_KEY_MAXZ: ((uint32_t *)colarr)[cind]=ci[CCOL_MAXZ];break;
case UI_KEY_W1:
case UI_KEY_W2:
@@ -3006,8 +3284,9 @@ columns_fill(struct mkcatalog_passparams *pp)
case UI_KEY_STD:
((float *)colarr)[cind] =
- gal_statistics_std_from_sums(oi[ CCOL_SUM ], oi[ CCOL_SUMP2 ],
- oi[ CCOL_NUM ]);
+ gal_statistics_std_from_sums(oi[ CCOL_SUM ],
+ oi[ CCOL_SUMP2 ],
+ oi[ CCOL_NUM ]);
break;
case UI_KEY_MEDIAN:
@@ -3085,9 +3364,9 @@ columns_fill(struct mkcatalog_passparams *pp)
break;
case UI_KEY_RIVERMEAN:
- ((float *)colarr)[cind] = ( ci[ CCOL_RIV_NUM]
- ? ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM]
- : NAN );
+ ((float *)colarr)[cind]=(ci[ CCOL_RIV_NUM]
+ ? ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM]
+ : NAN );
break;
case UI_KEY_RIVERNUM:
@@ -3104,8 +3383,8 @@ columns_fill(struct mkcatalog_passparams *pp)
break;
case UI_KEY_SKYSTD:
- ((float *)colarr)[cind] = sqrt( MKC_RATIO( ci[ CCOL_SUMVAR ],
- ci[ CCOL_NUMVAR ] ));
+ ((float *)colarr)[cind] = sqrt( MKC_RATIO(ci[ CCOL_SUMVAR ],
+ ci[ CCOL_NUMVAR ]));
break;
case UI_KEY_SEMIMAJOR:
diff --git a/bin/mkcatalog/main.h b/bin/mkcatalog/main.h
index 146c99f7..3d002c9c 100644
--- a/bin/mkcatalog/main.h
+++ b/bin/mkcatalog/main.h
@@ -132,6 +132,17 @@ enum objectcols
OCOL_C_GZ, /* Geometric center of clumps in object Z. */
OCOL_C_SUMWHT, /* Sum of positive image pixels for wht. */
OCOL_C_NUMWHT, /* Num of positive image pixels for wht. */
+ OCOL_NUMINSLICE, /* Number of used values in slice. */
+ OCOL_SUMINSLICE, /* Sum of values in each slice of label. */
+ OCOL_NUMALLINSLICE, /* Number of labeled pixels in slice. */
+ OCOL_SUMVARINSLICE, /* Sum of variance (including values). */
+ OCOL_SUMPROJINSLICE, /* Sum of projected area on each slice. */
+ OCOL_NUMPROJINSLICE, /* Sum of projected area on each slice. */
+ OCOL_SUMPROJVARINSLICE,/* Error in sum of projected area. */
+ OCOL_NUMOTHERINSLICE,/* Area of other labels in projected area. */
+ OCOL_SUMOTHERINSLICE,/* Sum of other objects in projected area. */
+ OCOL_SUMOTHERVARINSLICE,/* Variance in sum of other in proj. area.*/
+ OCOL_NUMALLOTHERINSLICE,/* Area of other labels in projected area.*/
OCOL_NUMCOLS, /* SHOULD BE LAST: total number of columns. */
};
@@ -206,6 +217,27 @@ enum clumpcols
+/* IDs for vector columns, which need a separate allocation. The names
+ should be the same as the 'OCOL_', just the prefix differs. */
+enum vector_cols
+ {
+ VEC_NUMINSLICE,
+ VEC_SUMINSLICE,
+ VEC_NUMALLINSLICE,
+ VEC_SUMVARINSLICE,
+ VEC_SUMPROJINSLICE,
+ VEC_NUMPROJINSLICE,
+ VEC_SUMPROJVARINSLICE,
+ VEC_NUMOTHERINSLICE,
+ VEC_SUMOTHERINSLICE,
+ VEC_SUMOTHERVARINSLICE,
+ VEC_NUMALLOTHERINSLICE,
+
+ VEC_NUM,
+ };
+
+
+
/* Main program parameters structure */
@@ -232,7 +264,6 @@ struct mkcatalogparams
uint8_t subtractsky; /* ==1: subtract the Sky from values. */
float sfmagnsigma; /* Surface brightness multiple of sigma.*/
float sfmagarea; /* Surface brightness area (arcsec^2). */
- uint8_t spectrum; /* Object spectrum for 3D datasets. */
uint8_t inbetweenints; /* Keep rows (integer ids) with no labs.*/
double sigmaclip[2]; /* Sigma clip column settings. */
@@ -244,7 +275,6 @@ struct mkcatalogparams
double upsigmaclip[2]; /* Sigma clip to measure upper limit. */
float upnsigma; /* Multiple of sigma to define up-lim. */
int32_t checkuplim[2]; /* Object & clump ID to check dist. */
-
gal_data_t *fracmax; /* Fractions to use in --fracsumarea. */
float spatialresolution; /* Error in area (used in SB error). */
@@ -259,7 +289,7 @@ struct mkcatalogparams
gal_data_t *upmask; /* Upper limit magnitude mask. */
float medstd; /* Median standard deviation value. */
float cpscorr; /* Counts-per-second correction. */
- int32_t *outlabs; /* Labels in output catalog (when necessary) */
+ int32_t *outlabs; /* Labels in output cat (when necessary)*/
int32_t *outlabsinv; /* Inverse of the 'outlabs' array. */
size_t numobjects; /* Number of object labels in image. */
float clumpsn; /* Clump S/N threshold. */
@@ -282,8 +312,6 @@ struct mkcatalogparams
uint8_t uprangewarning; /* A warning must be printed. */
size_t *hostobjid_c; /* To sort the clumps table by Obj.ID. */
size_t *numclumps_c; /* To sort the clumps table by Obj.ID. */
- gal_data_t *specsliceinfo; /* Slice information for spectra. */
- gal_data_t *spectra; /* Array of datasets containing spectra.*/
double pixelarcsecsq; /* Area of input's pixels in arcsec^2. */
char *usedvaluesfile; /* Ptr to final name used for values. */
diff --git a/bin/mkcatalog/mkcatalog.c b/bin/mkcatalog/mkcatalog.c
index 04b79913..f107f757 100644
--- a/bin/mkcatalog/mkcatalog.c
+++ b/bin/mkcatalog/mkcatalog.c
@@ -89,59 +89,120 @@ mkcatalog_clump_starting_index(struct mkcatalog_passparams
*pp)
-
-/* Each thread will call this function once. It will go over all the
- objects that are assigned to it. */
-static void *
-mkcatalog_single_object(void *in_prm)
+/* Vector allocation (short name is used since it is repeated a lot). */
+static void
+mkcatalog_vec_alloc(struct mkcatalog_passparams *pp, size_t onum,
+ size_t vnum, uint8_t type)
{
- struct gal_threads_params *tprm=(struct gal_threads_params *)in_prm;
- struct mkcatalogparams *p=(struct mkcatalogparams *)(tprm->params);
- size_t ndim=p->objects->ndim;
+ if( pp->p->oiflag[ onum ] )
+ gal_data_initialize(&pp->vector[vnum], 0, type, 1,
+ &(pp->p->objects->dsize[0]), NULL, 1,
+ pp->p->cp.minmapsize, pp->p->cp.quietmmap,
+ NULL, NULL, NULL);
+}
+
- size_t i;
- uint8_t *oif=p->oiflag;
- struct mkcatalog_passparams pp;
+
+/* Allocate all the necessary space. */
+static void
+mkcatalog_single_object_init(struct mkcatalogparams *p,
+ struct mkcatalog_passparams *pp)
+{
+ uint8_t *oif=p->oiflag;
+ size_t ndim=p->objects->ndim;
+ uint8_t i32=GAL_TYPE_INT32, f64=GAL_TYPE_FLOAT64; /* For short lines.*/
+
/* Initialize the mkcatalog_passparams elements. */
- pp.p = p;
- pp.clumpstartindex = 0;
- pp.rng = p->rng ? gsl_rng_clone(p->rng) : NULL;
- pp.oi = gal_pointer_allocate(GAL_TYPE_FLOAT64, OCOL_NUMCOLS,
- 0, __func__, "pp.oi");
+ pp->p = p;
+ pp->clumpstartindex = 0;
+ pp->rng = p->rng ? gsl_rng_clone(p->rng) : NULL;
+ pp->oi = gal_pointer_allocate(GAL_TYPE_FLOAT64,
+ OCOL_NUMCOLS, 0, __func__,
+ "pp->oi");
/* If we have second order measurements, allocate the array keeping the
temporary shift values for each object of this thread. Note that the
clumps catalog (if requested), will have the same measurements, so its
just enough to check the objects. */
- pp.shift = ( ( oif[ OCOL_GXX ]
- || oif[ OCOL_GYY ]
- || oif[ OCOL_GXY ]
- || oif[ OCOL_VXX ]
- || oif[ OCOL_VYY ]
- || oif[ OCOL_VXY ] )
- ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0, __func__,
- "pp.shift")
- : NULL );
+ pp->shift = ( ( oif[ OCOL_GXX ]
+ || oif[ OCOL_GYY ]
+ || oif[ OCOL_GXY ]
+ || oif[ OCOL_VXX ]
+ || oif[ OCOL_VYY ]
+ || oif[ OCOL_VXY ] )
+ ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0, __func__,
+ "pp->shift")
+ : NULL );
/* If we have upper-limit mode, then allocate the container to keep the
values to calculate the standard deviation. */
if(p->upperlimit)
{
/* Allocate the space to keep the upper-limit values. */
- pp.up_vals = gal_data_alloc(NULL, GAL_TYPE_FLOAT32, 1, &p->upnum,
- NULL, 0, p->cp.minmapsize, p->cp.quietmmap,
- NULL, NULL, NULL);
+ pp->up_vals = gal_data_alloc(NULL, GAL_TYPE_FLOAT32, 1, &p->upnum,
+ NULL, 0, p->cp.minmapsize,
+ p->cp.quietmmap, NULL, NULL, NULL);
/* Set the blank checked flag to 1. By definition, this dataset won't
have any blank values. Also 'flag' is initialized to '0'. So we
just have to set the checked flag ('GAL_DATA_FLAG_BLANK_CH') to
one to inform later steps that there are no blank values. */
- pp.up_vals->flag |= GAL_DATA_FLAG_BLANK_CH;
+ pp->up_vals->flag |= GAL_DATA_FLAG_BLANK_CH;
}
else
- pp.up_vals=NULL;
+ pp->up_vals=NULL;
+
+ /* If any vector measurements are necessary, do the necessary
+ allocations: first the general array, to keep all that are necessary,
+ then the individual ones. */
+ pp->vector = ( ( oif[ OCOL_NUMINSLICE ]
+ || oif[ OCOL_SUMINSLICE ]
+ || oif[ OCOL_NUMALLINSLICE ]
+ || oif[ OCOL_SUMVARINSLICE ]
+ || oif[ OCOL_SUMPROJINSLICE ]
+ || oif[ OCOL_NUMPROJINSLICE ]
+ || oif[ OCOL_SUMPROJVARINSLICE ]
+ || oif[ OCOL_NUMOTHERINSLICE ]
+ || oif[ OCOL_SUMOTHERINSLICE ]
+ || oif[ OCOL_SUMOTHERVARINSLICE ]
+ || oif[ OCOL_NUMALLOTHERINSLICE ] )
+ ? gal_data_array_calloc(VEC_NUM)
+ : NULL );
+ mkcatalog_vec_alloc(pp, OCOL_NUMINSLICE, VEC_NUMINSLICE, i32);
+ mkcatalog_vec_alloc(pp, OCOL_NUMALLINSLICE, VEC_NUMALLINSLICE, i32);
+ mkcatalog_vec_alloc(pp, OCOL_NUMPROJINSLICE, VEC_NUMPROJINSLICE, i32);
+ mkcatalog_vec_alloc(pp, OCOL_NUMOTHERINSLICE, VEC_NUMOTHERINSLICE,i32);
+ mkcatalog_vec_alloc(pp, OCOL_SUMINSLICE, VEC_SUMINSLICE, f64);
+ mkcatalog_vec_alloc(pp, OCOL_SUMVARINSLICE, VEC_SUMVARINSLICE, f64);
+ mkcatalog_vec_alloc(pp, OCOL_SUMPROJINSLICE, VEC_SUMPROJINSLICE, f64);
+ mkcatalog_vec_alloc(pp, OCOL_SUMOTHERINSLICE, VEC_SUMOTHERINSLICE,f64);
+ mkcatalog_vec_alloc(pp, OCOL_SUMOTHERVARINSLICE, VEC_SUMOTHERVARINSLICE,
+ f64);
+ mkcatalog_vec_alloc(pp, OCOL_NUMALLOTHERINSLICE, VEC_NUMALLOTHERINSLICE,
+ i32);
+ mkcatalog_vec_alloc(pp, OCOL_SUMPROJVARINSLICE, VEC_SUMPROJVARINSLICE,
+ f64);
+}
+
+
+
+
+
+/* Each thread will call this function once. It will go over all the
+ objects that are assigned to it. */
+static void *
+mkcatalog_single_object(void *in_prm)
+{
+ struct gal_threads_params *tprm=(struct gal_threads_params *)in_prm;
+ struct mkcatalogparams *p=(struct mkcatalogparams *)(tprm->params);
+
+ size_t i;
+ struct mkcatalog_passparams pp;
+
+ /* Initialize and allocate all the necessary values. */
+ mkcatalog_single_object_init(p, &pp);
/* Fill the desired columns for all the objects given to this thread. */
for(i=0; tprm->indexs[i]!=GAL_BLANK_SIZE_T; ++i)
@@ -153,7 +214,6 @@ mkcatalog_single_object(void *in_prm)
? p->outlabs[ tprm->indexs[i] ]
: tprm->indexs[i] + 1 );
pp.tile = &p->tiles[ tprm->indexs[i] ];
- pp.spectrum = &p->spectra[ tprm->indexs[i] ];
/* Initialize the parameters for this object/tile. */
parse_initialize(&pp);
@@ -181,16 +241,16 @@ mkcatalog_single_object(void *in_prm)
/* If an order-based calculation is requested, another pass is
necessary. */
- if( p->oiflag[ OCOL_MEDIAN ]
- || p->oiflag[ OCOL_MAXIMUM ]
- || p->oiflag[ OCOL_HALFMAXSUM ]
- || p->oiflag[ OCOL_HALFMAXNUM ]
- || p->oiflag[ OCOL_HALFSUMNUM ]
- || p->oiflag[ OCOL_SIGCLIPNUM ]
- || p->oiflag[ OCOL_SIGCLIPSTD ]
- || p->oiflag[ OCOL_SIGCLIPMEAN ]
- || p->oiflag[ OCOL_FRACMAX1NUM ]
- || p->oiflag[ OCOL_FRACMAX2NUM ]
+ if( p->oiflag[ OCOL_MEDIAN ]
+ || p->oiflag[ OCOL_MAXIMUM ]
+ || p->oiflag[ OCOL_HALFMAXSUM ]
+ || p->oiflag[ OCOL_HALFMAXNUM ]
+ || p->oiflag[ OCOL_HALFSUMNUM ]
+ || p->oiflag[ OCOL_SIGCLIPNUM ]
+ || p->oiflag[ OCOL_SIGCLIPSTD ]
+ || p->oiflag[ OCOL_SIGCLIPMEAN ]
+ || p->oiflag[ OCOL_FRACMAX1NUM ]
+ || p->oiflag[ OCOL_FRACMAX2NUM ]
|| p->oiflag[ OCOL_SIGCLIPMEDIAN ])
parse_order_based(&pp);
@@ -209,6 +269,7 @@ mkcatalog_single_object(void *in_prm)
free(pp.shift);
gal_data_free(pp.up_vals);
if(pp.rng) gsl_rng_free(pp.rng);
+ gal_data_array_free(pp.vector, VEC_NUM, 1);
/* Wait until all the threads finish and return. */
if(tprm->b) pthread_barrier_wait(tprm->b);
@@ -394,8 +455,8 @@ mkcatalog_outputs_keys_infiles(struct mkcatalogparams *p,
if(p->sky->size==1)
mkcatalog_outputs_keys_numeric(keylist, p->sky->array,
p->sky->type, "INSKYVAL",
- "Value of Sky used (a single number).",
- NULL);
+ "Value of Sky used (a single "
+ "number).", NULL);
else
{
gal_fits_key_write_filename("INSKY", p->usedskyfile, keylist, 0,
@@ -488,7 +549,8 @@ mkcatalog_outputs_keys(struct mkcatalogparams *p, int o0c1)
"mag");
/* Add the title for the keywords. */
- gal_fits_key_list_title_add_end(&keylist, "Surface brightness limit (SBL)",
0);
+ gal_fits_key_list_title_add_end(&keylist, "Surface brightness limit "
+ "(SBL)", 0);
/* Print surface brightness limit. */
if( !isnan(p->medstd) && !isnan(p->sfmagnsigma) )
@@ -496,12 +558,12 @@ mkcatalog_outputs_keys(struct mkcatalogparams *p, int
o0c1)
/* Used noise value (per pixel) and multiple of sigma. */
mkcatalog_outputs_keys_numeric(&keylist, &p->medstd,
GAL_TYPE_FLOAT32, "SBLSTD",
- "Pixel STD for surface brightness limit.",
- NULL);
+ "Pixel STD for surface brightness "
+ "limit.", NULL);
mkcatalog_outputs_keys_numeric(&keylist, &p->sfmagnsigma,
GAL_TYPE_FLOAT32, "SBLNSIG",
- "Sigma multiple for surface brightness "
- "limit.", NULL);
+ "Sigma multiple for surface "
+ "brightness limit.", NULL);
/* Only print magnitudes if a zeropoint is given. */
if( !isnan(p->zeropoint) )
@@ -511,8 +573,8 @@ mkcatalog_outputs_keys(struct mkcatalogparams *p, int o0c1)
p->zeropoint);
mkcatalog_outputs_keys_numeric(&keylist, &fvalue,
GAL_TYPE_FLOAT32, "SBLMAGPX",
- "Surface brightness limit per pixel.",
- "mag/pix");
+ "Surface brightness limit per "
+ "pixel.", "mag/pix");
/* Only print the SBL in fixed area if a WCS is present and a
pixel area could be deduced. */
@@ -532,7 +594,8 @@ mkcatalog_outputs_keys(struct mkcatalogparams *p, int o0c1)
p->zeropoint);
mkcatalog_outputs_keys_numeric(&keylist, &fvalue,
GAL_TYPE_FLOAT32, "SBLMAG",
- "Surf. bright. limit in SBLAREA.",
+ "Surf. bright. limit in "
+ "SBLAREA.",
"mag/arcsec^2");
}
else
@@ -646,8 +709,6 @@ sort_clumps_by_objid(struct mkcatalogparams *p)
static void
mkcatalog_write_outputs(struct mkcatalogparams *p)
{
- size_t i, scounter;
- char str[200], *fname;
gal_fits_list_key_t *keylist;
gal_list_str_t *comments=NULL;
int outisfits=gal_fits_name_is_fits(p->objectsout);
@@ -684,46 +745,6 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
}
}
- /* Spectra. */
- if(p->spectra)
- {
- /* Inform the user (Writing many FITS extensions can take
- long). */
- if(p->objectcols && outisfits)
- printf(" - Catalog(s) complete, writing spectra.\n");
-
- /* Start counting and writing the files. Note that due to some
- conditions (for example in debugging), a 'p->spectra[i]' may not
- actually contain any data. So we'll also count the number of
- spectra that are written. */
- scounter=0;
- for(i=0;i<p->numobjects;++i)
- if(p->spectra[i].ndim>0)
- {
- /* Increment the written spectra-counter. */
- ++scounter;
-
- /* Write the spectra based on the requested format. */
- if(outisfits)
- {
- /* Write the table. */
- sprintf(str, "SPECTRUM_%zu", i+1);
- gal_table_write(&p->spectra[i], NULL, NULL,
- GAL_TABLE_FORMAT_BFITS,
- p->objectsout, str, 0);
- }
- else
- {
- sprintf(str, "-spec-%zu.txt", i+1);
- fname=gal_checkset_automatic_output(&p->cp, p->objectsout,
- str);
- gal_table_write(&p->spectra[i], NULL, NULL,
GAL_TABLE_FORMAT_TXT,
- fname, NULL, 0);
- free(fname);
- }
- }
- }
-
/* Configuration information. */
if(outisfits)
{
@@ -735,36 +756,16 @@ mkcatalog_write_outputs(struct mkcatalogparams *p)
/* Inform the user */
- if(!p->cp.quiet)
+ if(!p->cp.quiet && p->objectcols)
{
- if(p->objectcols)
+ if(p->clumpsout && strcmp(p->clumpsout,p->objectsout))
{
- if(p->clumpsout && strcmp(p->clumpsout,p->objectsout))
- {
- printf(" - Output objects catalog: %s\n", p->objectsout);
- if(p->clumps)
- printf(" - Output clumps catalog: %s\n", p->clumpsout);
- }
- else
- printf(" - Catalog written to %s\n", p->objectsout);
-
- }
-
- if(p->spectra)
- {
- if(outisfits)
- {
- if(p->objectcols)
- printf(" - Spectra in %zu extensions named 'SPECTRUM_NN'.\n",
- p->numobjects);
- else
- printf(" - Output: %s (Spectra in %zu extensions named "
- "'SPECTRUM_NN').\n)", p->objectsout, p->numobjects);
- }
- else
- printf(" - Spectra in %zu files with '-spec-NN.txt' suffix.\n",
- p->numobjects);
+ printf(" - Output objects catalog: %s\n", p->objectsout);
+ if(p->clumps)
+ printf(" - Output clumps catalog: %s\n", p->clumpsout);
}
+ else
+ printf(" - Catalog written to %s\n", p->objectsout);
}
}
diff --git a/bin/mkcatalog/mkcatalog.h b/bin/mkcatalog/mkcatalog.h
index d2604bab..c9c6a845 100644
--- a/bin/mkcatalog/mkcatalog.h
+++ b/bin/mkcatalog/mkcatalog.h
@@ -23,6 +23,11 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#ifndef MKCATALOG_H
#define MKCATALOG_H
+
+
+
+
+/* Main structure for parsing individual objects. */
struct mkcatalog_passparams
{
struct mkcatalogparams *p; /* Main MakeCatalog paramers. */
@@ -41,7 +46,7 @@ struct mkcatalog_passparams
gsl_rng *rng; /* Random number generator. */
size_t clumpstartindex; /* Clump starting row in final catalog. */
gal_data_t *up_vals; /* Container for upper-limit values. */
- gal_data_t *spectrum; /* Spectrum of each object. */
+ gal_data_t *vector; /* Array of datasets for raw vectors. */
};
void
diff --git a/bin/mkcatalog/parse.c b/bin/mkcatalog/parse.c
index 09ffa876..63bc4fdc 100644
--- a/bin/mkcatalog/parse.c
+++ b/bin/mkcatalog/parse.c
@@ -44,6 +44,10 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
+
+
+
+
/* Both passes are going to need their starting pointers set, so we'll do
that here. */
void
@@ -51,16 +55,22 @@ parse_initialize(struct mkcatalog_passparams *pp)
{
struct mkcatalogparams *p=pp->p;
+ gal_data_t *vec;
size_t i, ndim=p->objects->ndim;
size_t *start_end=pp->start_end_inc;
/* Initialize the number of clumps in this object. */
pp->clumpsinobj=0;
-
/* Initialize the intermediate values to zero. */
memset(pp->oi, 0, OCOL_NUMCOLS * sizeof *pp->oi);
-
+ if(pp->vector)
+ for(i=0;i<VEC_NUM;++i)
+ {
+ vec=&(pp->vector[i]);
+ if(pp->vector[i].array)
+ memset(vec->array, 0, vec->size*gal_type_sizeof(vec->type));
+ }
/* Set the shifts in every dimension to avoid round-off errors in large
numbers for the non-linear calculations. We are using the first pixel
@@ -72,9 +82,9 @@ parse_initialize(struct mkcatalog_passparams *pp)
if(pp->shift)
{
/* Get the coordinates of the tile's starting point. */
- gal_dimension_index_to_coord( ( (float *)(pp->tile->array)
- - (float *)(pp->tile->block->array) ),
- ndim, p->objects->dsize, pp->shift);
+ gal_dimension_index_to_coord(( (float *)(pp->tile->array)
+ - (float *)(pp->tile->block->array) ),
+ ndim, p->objects->dsize, pp->shift);
/* Change their counting to start from 1, not zero, since we will be
using them as FITS coordinates. */
@@ -107,14 +117,14 @@ parse_initialize(struct mkcatalog_passparams *pp)
static size_t *
-parse_spectrum_pepare(struct mkcatalog_passparams *pp, size_t *start_end_inc,
- int32_t **st_o, float **st_v, float **st_std)
+parse_vector_dim3_prepare(struct mkcatalog_passparams *pp,
+ size_t *start_end_inc, int32_t **st_o,
+ float **st_v, float **st_std)
{
size_t *tsize;
gal_data_t *spectile;
struct mkcatalogparams *p=pp->p;
- size_t coord[3], minmax[6], numslices=p->objects->dsize[0];
- gal_data_t *area, *sum, *esum, *proj, *eproj, *oarea, *osum, *oesum;
+ size_t coord[3], minmax[6];
/* Get the coordinates of the spectral tile's starting element, then make
the tile. */
@@ -122,10 +132,10 @@ parse_spectrum_pepare(struct mkcatalog_passparams *pp,
size_t *start_end_inc,
pp->tile->array,
p->objects->type),
p->objects->ndim, p->objects->dsize, coord);
- minmax[0]=0; /* Changed to first slice.*/
+ minmax[0]=0; /* Changed to first slice.*/
minmax[1]=coord[1];
minmax[2]=coord[2];
- minmax[3]=p->objects->dsize[0]-1; /* Changed to last slice. */
+ minmax[3]=p->objects->dsize[0]-1; /* Changed to last slice. */
minmax[4]=coord[1]+pp->tile->dsize[1]-1;
minmax[5]=coord[2]+pp->tile->dsize[2]-1;
spectile=gal_tile_series_from_minmax(p->objects, minmax, 1);
@@ -140,54 +150,6 @@ parse_spectrum_pepare(struct mkcatalog_passparams *pp,
size_t *start_end_inc,
: NULL )
: NULL );
- /* Allocate the columns. */
- area = gal_data_alloc(NULL, GAL_TYPE_UINT32, 1, &numslices, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap, "AREA",
- "counter", "Area of object in a slice");
- sum = gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap, "SUM",
- p->values->unit, "Sum of values with this label.");
- esum = gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap, "SUM_ERR",
- p->values->unit, "Error in SUM column.");
- proj = gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap, "SUM_PROJECTED",
- p->values->unit, "Sum of full projected 2D area on "
- "a slice.");
- eproj = gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap,
"SUM_PROJECTED_ERR",
- p->values->unit, "Error in SUM_PROJECTED column.");
- oarea = gal_data_alloc(NULL, GAL_TYPE_UINT32, 1, &numslices, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap, "AREA_OTHER",
- "counter", "Area covered by other labels in a
slice.");
- osum = gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap, "SUM_OTHER",
- p->values->unit, "Sum of values in other labels on "
- "a slice.");
- oesum = gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap, "SUM_OTHER_ERR",
- p->values->unit, "Error in SUM_OTHER column.");
-
- /* Fill up the contents of the first element (note that the first
- 'gal_data_t' is actually in an array, so the skeleton is already
- allocated, we just have to allocate its contents. */
- gal_data_initialize(pp->spectrum, NULL, p->specsliceinfo->type, 1,
- &numslices, NULL, 0, p->cp.minmapsize,
- p->cp.quietmmap, NULL, NULL, NULL);
- gal_data_copy_to_allocated(p->specsliceinfo, pp->spectrum);
- pp->spectrum->next=gal_data_copy(p->specsliceinfo->next);
-
-
- /* Add all the other columns in the final spectrum table. */
- pp->spectrum->next->next = area;
- area->next = sum;
- area->next->next = esum;
- area->next->next->next = proj;
- area->next->next->next->next = eproj;
- area->next->next->next->next->next = oarea;
- area->next->next->next->next->next->next = osum;
- area->next->next->next->next->next->next->next = oesum;
-
/* Clean up and return. */
tsize=spectile->dsize;
spectile->dsize=NULL;
@@ -199,134 +161,49 @@ parse_spectrum_pepare(struct mkcatalog_passparams *pp,
size_t *start_end_inc,
-/* Since spectra will be a large table for many objects, it is very
- important to not consume too much space in for columns that don't need
- it. This function will check the integer columns and if they are smaller
- than the maximum values of smaller types, */
-static void
-parse_spectrum_uint32_to_best_type(gal_data_t **input)
-{
- gal_data_t *tmp=gal_statistics_maximum(*input);
-
- /* If maximum is smaller than UINT8_MAX, convert it to uint8_t */
- if( *(uint32_t *)(tmp->array) < UINT8_MAX )
- *input = gal_data_copy_to_new_type_free(*input, GAL_TYPE_UINT8);
-
- /* otherwise, if it is smaller than UINT16_MAX, convert it to uint16_t */
- else if( *(uint32_t *)(tmp->array) < UINT16_MAX )
- *input = gal_data_copy_to_new_type_free(*input, GAL_TYPE_UINT16);
-
- /* Clean up. */
- gal_data_free(tmp);
-}
-
-
-
-
-
-static void
-parse_spectrum_end(struct mkcatalog_passparams *pp, gal_data_t *xybin)
-{
- size_t i;
- double *searr, *pearr, *osearr;
- struct mkcatalogparams *p=pp->p;
-
- /* The datasets and their pointers. */
- gal_data_t *area = pp->spectrum->next->next;
- gal_data_t *sum = area->next;
- gal_data_t *esum = area->next->next;
- gal_data_t *proj = area->next->next->next;
- gal_data_t *eproj = area->next->next->next->next;
- gal_data_t *oarea = area->next->next->next->next->next;
- gal_data_t *osum = area->next->next->next->next->next->next;
- gal_data_t *oesum = area->next->next->next->next->next->next->next;
-
- /* Apply corrections to the columns that need it. */
- searr = esum->array;
- pearr = eproj->array;
- osearr = oesum->array;
- for(i=0; i<p->objects->dsize[0]; ++i)
- {
- searr[i] = sqrt( searr[i] );
- pearr[i] = sqrt( pearr[i] );
- osearr[i] = sqrt( osearr[i] );
- }
-
- /* Convert the 'double' type columns to 'float'. The extra precision of
- 'double' was necessary when we were summing values in each slice. But
- afterwards, it is not necessary at all (the measurement error is much
- larger than a double-precision floating point number (15
- decimals). But the extra space gained (double) is very useful in not
- wasting too much memory and hard-disk space or online transfer time.*/
- sum = gal_data_copy_to_new_type_free(sum, GAL_TYPE_FLOAT32);
- esum = gal_data_copy_to_new_type_free(esum, GAL_TYPE_FLOAT32);
- proj = gal_data_copy_to_new_type_free(proj, GAL_TYPE_FLOAT32);
- eproj = gal_data_copy_to_new_type_free(eproj, GAL_TYPE_FLOAT32);
- osum = gal_data_copy_to_new_type_free(osum, GAL_TYPE_FLOAT32);
- oesum = gal_data_copy_to_new_type_free(oesum, GAL_TYPE_FLOAT32);
-
- /* For the two area columns, find their maximum value and convert the
- dataset to the smallest type that can hold them. */
- parse_spectrum_uint32_to_best_type(&area);
- parse_spectrum_uint32_to_best_type(&oarea);
-
- /* List the datasets and write them into the pointer for this object
- (exact copy of the statement in 'parse_spectrum_pepare'). */
- pp->spectrum->next->next = area;
- area->next = sum;
- area->next->next = esum;
- area->next->next->next = proj;
- area->next->next->next->next = eproj;
- area->next->next->next->next->next = oarea;
- area->next->next->next->next->next->next = osum;
- area->next->next->next->next->next->next->next = oesum;
-}
-
-
-
-
-/* Each spectrum is a multi-column table (note that the slice counter and
- wavelength are written in the end):
-
- Column 3: Number of object pixels.
- Column 4: Sum of object pixel values.
- Column 5: Error in Column 2.
- Column 6: Sum over all 2D projection over whole specturm.
- Column 7: Error in Column 4.
- Column 8: Area of other labels in this slice.
- Column 9: Flux by other objects in projected area.
- Column 10: Error in Column 9.
- */
static void
-parse_spectrum(struct mkcatalog_passparams *pp, gal_data_t *xybin)
+parse_vector_dim3(struct mkcatalog_passparams *pp, gal_data_t *xybin)
{
struct mkcatalogparams *p=pp->p;
- gal_data_t *area;
- float *st_v, *st_std;
- uint32_t *narr, *oarr;
- size_t nproj=0, *tsize, start_end_inc[2];
+ double var;
+ int needsvar;
+ gal_data_t *vector=pp->vector;
+ float *std=p->std?p->std->array:NULL;
+ size_t c[3], *dsize=p->objects->dsize;
+ size_t sind=0, pind=0, num_increment=1;
uint8_t *xybinarr = xybin ? xybin->array : NULL;
- int32_t *O, *OO, *st_o, *objarr=p->objects->array;
- size_t tid, *dsize=p->objects->dsize, num_increment=1;
- double var, *sarr, *searr, *parr, *pearr, *osarr, *osearr;
- size_t increment=0, pind=0, sind=0, ndim=p->objects->ndim, c[3];
- float st, sval, *V=NULL, *ST=NULL, *std=p->std?p->std->array:NULL;
-
- /* Prepare the columns to write in. */
- tsize = parse_spectrum_pepare(pp, start_end_inc, &st_o, &st_v, &st_std);
- area = pp->spectrum->next->next;
- narr = area->array;
- sarr = area->next->array;
- searr = area->next->next->array;
- parr = area->next->next->next->array;
- pearr = area->next->next->next->next->array;
- oarr = area->next->next->next->next->next->array;
- osarr = area->next->next->next->next->next->next->array;
- osearr = area->next->next->next->next->next->next->next->array;
-
- /* If tile-id isn't necessary, set 'tid' to a blank value. */
- tid = (p->std && p->std->size>1 && st_std == NULL) ? 0 : GAL_BLANK_SIZE_T;
+ float st, sval, *st_v, *st_std, *V=NULL, *ST=NULL;
+ int32_t *st_o, *O, *OO, *objarr=p->objects->array;
+ size_t tid, *tsize, increment=0, start_end_inc[2], ndim=p->objects->ndim;
+
+ /* Pointers to necessary temporary arrays (they will be NULL if they are
+ not necessary for the user). */
+ double *suminslice = vector[ VEC_SUMINSLICE ].array;
+ double *sumvarinslice = vector[ VEC_SUMVARINSLICE ].array;
+ double *sumprojinslice = vector[ VEC_SUMPROJINSLICE ].array;
+ double *sumprojvarinslice = vector[ VEC_SUMPROJVARINSLICE ].array;
+ double *sumotherinslice = vector[ VEC_SUMOTHERINSLICE ].array;
+ double *sumothervarinslice = vector[ VEC_SUMOTHERVARINSLICE ].array;
+ int32_t *numinslice = vector[ VEC_NUMINSLICE ].array;
+ int32_t *numallinslice = vector[ VEC_NUMALLINSLICE ].array;
+ int32_t *numprojinslice = vector[ VEC_NUMPROJINSLICE ].array;
+ int32_t *numotherinslice = vector[ VEC_NUMOTHERINSLICE ].array;
+ int32_t *numallotherinslice = vector[ VEC_NUMALLOTHERINSLICE ].array;
+
+ /* Prepare the parsing information. Also, if tile-id isn't necessary, set
+ 'tid' to a blank value to cause a crash with a mistake. */
+ tsize=parse_vector_dim3_prepare(pp, start_end_inc, &st_o, &st_v, &st_std);
+ tid = (p->std && p->std->size>1 && st_std == NULL)?0:GAL_BLANK_SIZE_T;
+
+ /* Check if we need the variance. */
+ needsvar = ( sumvarinslice || sumprojvarinslice || sumothervarinslice
+ ? 1 : 0 );
+ if(needsvar && p->std==NULL)
+ error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at '%s' to fix "
+ "the problem. The requested column requires a variance "
+ "estimation, but the input standard deviation image is NULL",
+ __func__, PACKAGE_BUGREPORT);
/* Parse each contiguous patch of memory covered by this object. */
while( start_end_inc[0] + increment <= start_end_inc[1] )
@@ -337,21 +214,27 @@ parse_spectrum(struct mkcatalog_passparams *pp,
gal_data_t *xybin)
if( p->std && st_std ) ST = st_std + increment;
OO = ( O = st_o + increment ) + pp->tile->dsize[ndim-1];
- /* Parse the tile. */
+ /* Parse the "tile" for this label. */
do
{
- /* Only continue if this voxel is useful: it isn't NaN, or its
- covered by the projected area or object's label. */
- if( !isnan(*V) && (xybin && xybinarr[pind]==2) )
+ /* Counters that don't depend on value. */
+ if(numallinslice) ++numallinslice[sind];
+ if(*O!=pp->object && numallotherinslice)
+ ++numallotherinslice[sind];
+
+ /* Only continue if this voxel is on a label and is useful (it
+ isn't NaN). */
+ if( !isnan(*V) )
{
- /* Get the error in measuing this pixel's flux. */
- if(p->std)
+ /* Variance of this voxel (if necessary) */
+ if(needsvar)
{
/* If the standard deviation is given on a tile
structure, estimate the tile ID. */
if(tid != GAL_BLANK_SIZE_T)
{
- gal_dimension_index_to_coord(O-objarr, ndim, dsize, c);
+ gal_dimension_index_to_coord(O-objarr, ndim, dsize,
+ c);
tid=gal_tile_full_id_from_coord(&p->cp.tl, c);
}
@@ -364,34 +247,35 @@ parse_spectrum(struct mkcatalog_passparams *pp,
gal_data_t *xybin)
}
else var = NAN;
+ /* Only on this label. */
+ if(*O==pp->object) /* We are on this object. */
+ {
+ if(numinslice) ++numinslice[sind];
+ if(suminslice) suminslice[sind] += *V;
+ if(sumvarinslice) sumvarinslice[sind] += var;
+ }
- /* Projected spectra: see if we have a value of '2' in the
- 'xybin' array (showing that there is atleast one non-blank
- element there over the whole spectrum. */
- ++nproj;
- parr [ sind ] += *V;
- pearr[ sind ] += var;
-
- /* Calculate the number of labeled/detected pixels that
- don't belong to this object. */
- if(*O>0)
+ /* Projected measurements: see if we have a value of '2' in
+ the 'xybin' array (showing that there is atleast one
+ non-blank element there over the whole spectrum. */
+ if(xybin && xybinarr[pind]==2)
{
- if(*O==pp->object)
- {
- ++narr[ sind ];
- sarr [ sind ] += *V;
- searr [ sind ] += var;
- }
- else
+ /* Raw measurements over the projection. */
+ if(numprojinslice) ++numprojinslice[sind];
+ if(sumprojinslice) sumprojinslice[sind] += *V;
+ if(sumprojvarinslice) sumprojvarinslice[sind] += var;
+
+ /* Other labels over this projection. */
+ if(*O!=pp->object)
{
- ++oarr [ sind ];
- osarr [ sind ] += *V;
- osearr [ sind ] += var;
+ if(numotherinslice) ++numotherinslice[sind];
+ if(sumotherinslice) sumotherinslice[sind] += *V;
+ if(sumothervarinslice)sumothervarinslice[sind]+=var;
}
}
}
- /* Increment the pointers. */
+ /* Values used, increment the pointrs for next voxel. */
if( xybin ) ++pind;
if( p->values ) ++V;
if( p->std && st_std ) ++ST;
@@ -402,35 +286,35 @@ parse_spectrum(struct mkcatalog_passparams *pp,
gal_data_t *xybin)
increment += ( gal_tile_block_increment(p->objects, tsize,
num_increment++, NULL) );
- /* Increment the slice number, 'sind', and reset the projection (2D)
- index 'pind' if we have just finished parsing a slice. */
+ /* If we have reached the end of one slice, increment the slice index
+ ('sind'), and reset the projection (2D) index 'pind' if we have
+ just finished parsing a slice. Also, set all the sum values
+ that didn't have any measurement to NAN. */
if( (num_increment-1)%pp->tile->dsize[1]==0 )
{
/* If there was no measurement, set NaN for the values and their
errors (zero is meaningful). */
- if( nproj ==0 ) parr[sind] = pearr[sind] = NAN;
- if( narr[sind] ==0 ) sarr[sind] = searr[sind] = NAN;
- if( oarr[sind] ==0 ) osarr[sind] = osearr[sind] = NAN;
-
- nproj=pind=0;
+ if(numinslice && numinslice[sind]==0)
+ suminslice[sind]=NAN;
+ if(numprojinslice && numprojinslice[sind]==0)
+ sumprojinslice[sind]=NAN;
+ if(numotherinslice && numotherinslice[sind]==0)
+ sumotherinslice[sind]=NAN;
+
+ /* Set the projection-index to zero (since it counts on each
+ slice), and increment the slice-index. */
+ pind=0;
++sind;
}
}
- /* Finalize the spectrum generation and clean up. */
- parse_spectrum_end(pp, xybin);
+ /* Clean up and return. */
free(tsize);
-
- /* For a check.
- gal_table_write(pp->spectrum, NULL, NULL, GAL_TABLE_FORMAT_BFITS,
- "spectrum.fits", "SPECTRUM", 0);
- */
}
-
void
parse_objects(struct mkcatalog_passparams *pp)
{
@@ -462,21 +346,21 @@ parse_objects(struct mkcatalog_passparams *pp)
/* If any coordinate columns are requested. */
size_t *c = (
/* Coordinate-related columns. */
- ( oif[ OCOL_GX ]
- || oif[ OCOL_GY ]
- || oif[ OCOL_GZ ]
- || oif[ OCOL_VX ]
- || oif[ OCOL_VY ]
- || oif[ OCOL_VZ ]
- || oif[ OCOL_C_GX ]
- || oif[ OCOL_C_GY ]
- || oif[ OCOL_C_GZ ]
- || oif[ OCOL_MINVX ]
- || oif[ OCOL_MAXVX ]
- || oif[ OCOL_MINVY ]
- || oif[ OCOL_MAXVY ]
- || oif[ OCOL_MINVZ ]
- || oif[ OCOL_MAXVZ ]
+ ( oif[ OCOL_GX ]
+ || oif[ OCOL_GY ]
+ || oif[ OCOL_GZ ]
+ || oif[ OCOL_VX ]
+ || oif[ OCOL_VY ]
+ || oif[ OCOL_VZ ]
+ || oif[ OCOL_C_GX ]
+ || oif[ OCOL_C_GY ]
+ || oif[ OCOL_C_GZ ]
+ || oif[ OCOL_MINVX ]
+ || oif[ OCOL_MAXVX ]
+ || oif[ OCOL_MINVY ]
+ || oif[ OCOL_MAXVY ]
+ || oif[ OCOL_MINVZ ]
+ || oif[ OCOL_MAXVZ ]
|| oif[ OCOL_MINVNUM ]
|| oif[ OCOL_MAXVNUM ]
|| sc
@@ -484,14 +368,21 @@ parse_objects(struct mkcatalog_passparams *pp)
the coordinate to find which tile a pixel belongs
to. */
|| tid==GAL_BLANK_SIZE_T )
- ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0, __func__, "c")
+ ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0, __func__,
+ "c")
: NULL );
- /* If an XY projection area is necessary, we'll need to allocate an array
- to keep the projected space. */
- if( p->spectrum
- || oif[ OCOL_NUMALLXY ]
- || oif[ OCOL_NUMXY ] )
+ /* If any of the projection measurements are necessary, we need to
+ allocate an array to keep the projected space. */
+ if( oif[ OCOL_NUMALLXY ]
+ || oif[ OCOL_NUMXY ]
+ || oif[ OCOL_SUMPROJINSLICE ]
+ || oif[ OCOL_NUMPROJINSLICE ]
+ || oif[ OCOL_SUMPROJVARINSLICE ]
+ || oif[ OCOL_NUMOTHERINSLICE ]
+ || oif[ OCOL_SUMOTHERINSLICE ]
+ || oif[ OCOL_SUMOTHERVARINSLICE ]
+ || oif[ OCOL_NUMALLOTHERINSLICE ] )
{
xybin=gal_data_alloc(NULL, GAL_TYPE_UINT8, 2, &tsize[1], NULL,
1, p->cp.minmapsize, p->cp.quietmmap,
@@ -520,7 +411,7 @@ parse_objects(struct mkcatalog_passparams *pp)
/* INTERNAL: Get the number of clumps in this object: it is
the largest clump ID over each object. */
if( p->clumps && *C>0 )
- pp->clumpsinobj = *C > pp->clumpsinobj ? *C : pp->clumpsinobj;
+ pp->clumpsinobj = *C > pp->clumpsinobj?*C:pp->clumpsinobj;
/* Add to the area of this object. */
@@ -546,9 +437,9 @@ parse_objects(struct mkcatalog_passparams *pp)
if(pp->shift)
{
/* Calculate the shifted coordinates for second order
- calculations. The coordinate is incremented because
- from now on, the positions are in the FITS standard
- (starting from one). */
+ calculations. The coordinate is incremented
+ because from now on, the positions are in the FITS
+ standard (starting from one). */
for(d=0;d<ndim;++d) sc[d] = c[d] + 1 - pp->shift[d];
/* Include the shifted values, note that the second
@@ -562,9 +453,9 @@ parse_objects(struct mkcatalog_passparams *pp)
if(p->clumps && *C>0)
{
if(oif[ OCOL_C_NUMALL ]) oi[ OCOL_C_NUMALL ]++;
- if(oif[ OCOL_C_GX ]) oi[ OCOL_C_GX ] += c[ ndim-1 ]+1;
- if(oif[ OCOL_C_GY ]) oi[ OCOL_C_GY ] += c[ ndim-2 ]+1;
- if(oif[ OCOL_C_GZ ]) oi[ OCOL_C_GZ ] += c[ ndim-3 ]+1;
+ if(oif[ OCOL_C_GX ]) oi[ OCOL_C_GX ] += c[ndim-1]+1;
+ if(oif[ OCOL_C_GY ]) oi[ OCOL_C_GY ] += c[ndim-2]+1;
+ if(oif[ OCOL_C_GZ ]) oi[ OCOL_C_GZ ] += c[ndim-3]+1;
}
}
@@ -602,16 +493,16 @@ parse_objects(struct mkcatalog_passparams *pp)
{
minima_v = *V;
oi[ OCOL_MINVNUM ]=1;
- if(oif[OCOL_MINVX]) oi[ OCOL_MINVX ] = c[ ndim-1 ]+1;
- if(oif[OCOL_MINVY]) oi[ OCOL_MINVY ] = c[ ndim-2 ]+1;
- if(oif[OCOL_MINVZ]) oi[ OCOL_MINVZ ] = c[ ndim-3 ]+1;
+ if(oif[OCOL_MINVX])oi[OCOL_MINVX]=c[ndim-1]+1;
+ if(oif[OCOL_MINVY])oi[OCOL_MINVY]=c[ndim-2]+1;
+ if(oif[OCOL_MINVZ])oi[OCOL_MINVZ]=c[ndim-3]+1;
}
else
{
oi[ OCOL_MINVNUM ]++;
- if(oif[OCOL_MINVX]) oi[ OCOL_MINVX ] += c[ ndim-1
]+1;
- if(oif[OCOL_MINVY]) oi[ OCOL_MINVY ] += c[ ndim-2
]+1;
- if(oif[OCOL_MINVZ]) oi[ OCOL_MINVZ ] += c[ ndim-3
]+1;
+ if(oif[OCOL_MINVX])oi[OCOL_MINVX]+=c[ndim-1]+1;
+ if(oif[OCOL_MINVY])oi[OCOL_MINVY]+=c[ndim-2]+1;
+ if(oif[OCOL_MINVZ])oi[OCOL_MINVZ]+=c[ndim-3]+1;
}
}
if( oif[ OCOL_MAXVNUM ] && *V>=maxima_v )
@@ -620,16 +511,16 @@ parse_objects(struct mkcatalog_passparams *pp)
{
maxima_v = *V;
oi[ OCOL_MAXVNUM ]=1;
- if(oif[OCOL_MAXVX]) oi[ OCOL_MAXVX ] = c[ ndim-1 ]+1;
- if(oif[OCOL_MAXVY]) oi[ OCOL_MAXVY ] = c[ ndim-2 ]+1;
- if(oif[OCOL_MAXVZ]) oi[ OCOL_MAXVZ ] = c[ ndim-3 ]+1;
+ if(oif[OCOL_MAXVX])oi[OCOL_MAXVX]=c[ndim-1]+1;
+ if(oif[OCOL_MAXVY])oi[OCOL_MAXVY]=c[ndim-2]+1;
+ if(oif[OCOL_MAXVZ])oi[OCOL_MAXVZ]=c[ndim-3]+1;
}
else
{
oi[ OCOL_MAXVNUM ]++;
- if(oif[OCOL_MAXVX]) oi[ OCOL_MAXVX ] += c[ ndim-1
]+1;
- if(oif[OCOL_MAXVY]) oi[ OCOL_MAXVY ] += c[ ndim-2
]+1;
- if(oif[OCOL_MAXVZ]) oi[ OCOL_MAXVZ ] += c[ ndim-3
]+1;
+ if(oif[OCOL_MAXVX])oi[OCOL_MAXVX]+=c[ndim-1]+1;
+ if(oif[OCOL_MAXVY])oi[OCOL_MAXVY]+=c[ndim-2]+1;
+ if(oif[OCOL_MAXVZ])oi[OCOL_MAXVZ]+=c[ndim-3]+1;
}
}
@@ -639,9 +530,9 @@ parse_objects(struct mkcatalog_passparams *pp)
{
if(oif[ OCOL_NUMWHT ]) oi[ OCOL_NUMWHT ]++;
if(oif[ OCOL_SUMWHT ]) oi[ OCOL_SUMWHT ] += *V;
- if(oif[ OCOL_VX ]) oi[ OCOL_VX ] += *V*(c[ ndim-1 ]+1);
- if(oif[ OCOL_VY ]) oi[ OCOL_VY ] += *V*(c[ ndim-2 ]+1);
- if(oif[ OCOL_VZ ]) oi[ OCOL_VZ ] += *V*(c[ ndim-3 ]+1);
+ if(oif[ OCOL_VX ]) oi[ OCOL_VX ] += *V*(c[ndim-1]+1);
+ if(oif[ OCOL_VY ]) oi[ OCOL_VY ] += *V*(c[ndim-2]+1);
+ if(oif[ OCOL_VZ ]) oi[ OCOL_VZ ] += *V*(c[ndim-3]+1);
if(pp->shift)
{
oi[ OCOL_VXX ] += *V * sc[1] * sc[1];
@@ -651,7 +542,7 @@ parse_objects(struct mkcatalog_passparams *pp)
if(p->clumps && *C>0)
{
if(oif[ OCOL_C_NUMWHT ]) oi[ OCOL_C_NUMWHT ]++;
- if(oif[ OCOL_C_SUMWHT ]) oi[ OCOL_C_SUMWHT ] += *V;
+ if(oif[ OCOL_C_SUMWHT ]) oi[ OCOL_C_SUMWHT ]+=*V;
if(oif[ OCOL_C_VX ])
oi[ OCOL_C_VX ] += *V * (c[ ndim-1 ]+1);
if(oif[ OCOL_C_VY ])
@@ -667,10 +558,10 @@ parse_objects(struct mkcatalog_passparams *pp)
if(p->sky && oif[ OCOL_SUMSKY ])
{
skyval = ( pp->st_sky
- ? (isnan(*SK)?0:*SK) /* Full array
*/
+ ? (isnan(*SK)?0:*SK) /* Full array */
: ( p->sky->size>1
- ? (isnan(sky[tid])?0:sky[tid]) /* Tile
*/
- : sky[0] ) ); /* Single
value*/
+ ? (isnan(sky[tid])?0:sky[tid]) /* Tile */
+ : sky[0] ) ); /* Single value*/
if(!isnan(skyval))
{
oi[ OCOL_NUMSKY ]++;
@@ -682,8 +573,9 @@ parse_objects(struct mkcatalog_passparams *pp)
/* Sky standard deviation based measurements.*/
if(p->std)
{
- /* Calculate the variance and save it in the output if
necessary. */
- sval = pp->st_std ? *ST : (p->std->size>1?std[tid]:std[0]);
+ /* Calculate the variance and save it in the output if
+ necessary. */
+ sval=pp->st_std ? *ST : (p->std->size>1?std[tid]:std[0]);
var = p->variance ? sval : sval*sval;
if(oif[ OCOL_SUMVAR ] && (!isnan(var)))
{
@@ -746,17 +638,26 @@ parse_objects(struct mkcatalog_passparams *pp)
while(++u<uf);
/* For a check on the projected 2D areas.
- if(xybin && pp->object==2)
+ if(xybin && pp->object==1)
{
gal_fits_img_write(xybin, "xybin.fits", NULL, NULL);
- exit(0);
+ printf("Created 'xybin.fits'\n"); exit(0);
}
*/
}
/* Generate the Spectrum. */
- if(p->spectrum)
- parse_spectrum(pp, xybin);
+ if( oif[ OCOL_SUMINSLICE ]
+ || oif[ OCOL_NUMINSLICE ]
+ || oif[ OCOL_NUMALLINSLICE ]
+ || oif[ OCOL_SUMVARINSLICE ]
+ || oif[ OCOL_SUMPROJINSLICE ]
+ || oif[ OCOL_NUMOTHERINSLICE ]
+ || oif[ OCOL_SUMOTHERINSLICE ]
+ || oif[ OCOL_SUMPROJVARINSLICE ]
+ || oif[ OCOL_SUMOTHERVARINSLICE ]
+ || oif[ OCOL_NUMALLOTHERINSLICE ])
+ parse_vector_dim3(pp, xybin);
/* Clean up. */
if(c) free(c);
@@ -841,8 +742,8 @@ parse_clumps(struct mkcatalog_passparams *pp)
/* Coordinate shift. */
size_t *sc = ( pp->shift
- ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0, __func__,
- "sc")
+ ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0,
+ __func__, "sc")
: NULL );
/* If any coordinate columns are requested. */
@@ -868,8 +769,8 @@ parse_clumps(struct mkcatalog_passparams *pp)
|| cif[ CCOL_MAXVNUM ]
|| sc
|| tid==GAL_BLANK_SIZE_T )
- ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0, __func__,
- "c")
+ ? gal_pointer_allocate(GAL_TYPE_SIZE_T, ndim, 0,
+ __func__, "c")
: NULL );
/* Preparations for neighbor parsing. */
@@ -940,7 +841,8 @@ parse_clumps(struct mkcatalog_passparams *pp)
if(c)
{
/* Get "C" the coordinates of this point. */
- gal_dimension_index_to_coord(O-objects, ndim, dsize, c);
+ gal_dimension_index_to_coord(O-objects, ndim,
+ dsize, c);
/* Position extrema measurements. */
if(cif[ CCOL_MINX ])
@@ -969,7 +871,7 @@ parse_clumps(struct mkcatalog_passparams *pp)
{
/* Shifted coordinates for second order moments,
see explanations in the first pass.*/
- for(d=0;d<ndim;++d) sc[d] = c[d] + 1 - pp->shift[d];
+ for(d=0;d<ndim;++d) sc[d] = c[d]+1-pp->shift[d];
/* Raw second-order measurements. */
ci[ CCOL_GXX ] += sc[1] * sc[1];
@@ -1000,16 +902,22 @@ parse_clumps(struct mkcatalog_passparams *pp)
{
minima_v[cind] = *V;
ci[ CCOL_MINVNUM ]=1;
- if(cif[CCOL_MINVX]) ci[ CCOL_MINVX ] = c[ ndim-1
]+1;
- if(cif[CCOL_MINVY]) ci[ CCOL_MINVY ] = c[ ndim-2
]+1;
- if(cif[CCOL_MINVZ]) ci[ CCOL_MINVZ ] = c[ ndim-3
]+1;
+ if(cif[CCOL_MINVX])
+ ci[ CCOL_MINVX ] = c[ ndim-1 ]+1;
+ if(cif[CCOL_MINVY])
+ ci[ CCOL_MINVY ] = c[ ndim-2 ]+1;
+ if(cif[CCOL_MINVZ])
+ ci[ CCOL_MINVZ ] = c[ ndim-3 ]+1;
}
else
{
ci[ CCOL_MINVNUM ]++;
- if(cif[CCOL_MINVX]) ci[ CCOL_MINVX ] += c[
ndim-1 ]+1;
- if(cif[CCOL_MINVY]) ci[ CCOL_MINVY ] += c[
ndim-2 ]+1;
- if(cif[CCOL_MINVZ]) ci[ CCOL_MINVZ ] += c[
ndim-3 ]+1;
+ if(cif[CCOL_MINVX])
+ ci[ CCOL_MINVX ] += c[ ndim-1 ]+1;
+ if(cif[CCOL_MINVY])
+ ci[ CCOL_MINVY ] += c[ ndim-2 ]+1;
+ if(cif[CCOL_MINVZ])
+ ci[ CCOL_MINVZ ] += c[ ndim-3 ]+1;
}
}
if( cif[ CCOL_MAXVNUM ] && *V>=maxima_v[cind] )
@@ -1018,16 +926,22 @@ parse_clumps(struct mkcatalog_passparams *pp)
{
maxima_v[cind] = *V;
ci[ CCOL_MAXVNUM ]=1;
- if(cif[CCOL_MAXVX]) ci[ CCOL_MAXVX ] = c[ ndim-1
]+1;
- if(cif[CCOL_MAXVY]) ci[ CCOL_MAXVY ] = c[ ndim-2
]+1;
- if(cif[CCOL_MAXVZ]) ci[ CCOL_MAXVZ ] = c[ ndim-3
]+1;
+ if(cif[CCOL_MAXVX])
+ ci[ CCOL_MAXVX ] = c[ ndim-1 ]+1;
+ if(cif[CCOL_MAXVY])
+ ci[ CCOL_MAXVY ] = c[ ndim-2 ]+1;
+ if(cif[CCOL_MAXVZ])
+ ci[ CCOL_MAXVZ ] = c[ ndim-3 ]+1;
}
else
{
ci[ CCOL_MAXVNUM ]++;
- if(cif[CCOL_MAXVX]) ci[ CCOL_MAXVX ] += c[
ndim-1 ]+1;
- if(cif[CCOL_MAXVY]) ci[ CCOL_MAXVY ] += c[
ndim-2 ]+1;
- if(cif[CCOL_MAXVZ]) ci[ CCOL_MAXVZ ] += c[
ndim-3 ]+1;
+ if(cif[CCOL_MAXVX])
+ ci[ CCOL_MAXVX ] += c[ ndim-1 ]+1;
+ if(cif[CCOL_MAXVY])
+ ci[ CCOL_MAXVY ] += c[ ndim-2 ]+1;
+ if(cif[CCOL_MAXVZ])
+ ci[ CCOL_MAXVZ ] += c[ ndim-3 ]+1;
}
}
@@ -1302,22 +1216,22 @@ parse_area_of_frac_sum(struct mkcatalog_passparams *pp,
gal_data_t *values,
if(flag[ o1c0 ? OCOL_MAXIMUM : CCOL_MAXIMUM ])
outarr[ o1c0 ? OCOL_MAXIMUM : CCOL_MAXIMUM ] = max;
- /* The number of pixels within half the maximum. */
+ /* Number of pixels within half the maximum. */
if(flag[ o1c0 ? OCOL_HALFMAXNUM : CCOL_HALFMAXNUM ])
outarr[ o1c0 ? OCOL_HALFMAXNUM : CCOL_HALFMAXNUM ]
= parse_frac_find(sorted_d, max, 0.5f, 0);
- /* The number of pixels within the first requested fraction of maximum */
+ /* Number of pixels within the first requested fraction of maximum */
if(flag[ o1c0 ? OCOL_FRACMAX1NUM : CCOL_FRACMAX1NUM ])
outarr[ o1c0 ? OCOL_FRACMAX1NUM : CCOL_FRACMAX1NUM ]
= parse_frac_find(sorted_d, max, fracmax[0], 0);
- /* The number of pixels within the first requested fraction of maximum */
+ /* Number of pixels within the first requested fraction of maximum */
if(flag[ o1c0 ? OCOL_FRACMAX2NUM : CCOL_FRACMAX2NUM ])
outarr[ o1c0 ? OCOL_FRACMAX2NUM : CCOL_FRACMAX2NUM ]
= parse_frac_find(sorted_d, max, fracmax[1], 0);
- /* The sum of the pixels within the given fraction of the maximum. */
+ /* Sum of the pixels within the given fraction of the maximum. */
if( flag[ o1c0 ? OCOL_HALFMAXSUM : CCOL_HALFMAXSUM ] )
outarr[ o1c0 ? OCOL_HALFMAXSUM : CCOL_HALFMAXSUM ]
= parse_frac_sum(sorted_d, max, 0.5f, 0);
@@ -1361,32 +1275,32 @@ parse_order_based(struct mkcatalog_passparams *pp)
can just write NaN values for the necessary columns. */
if(tmpsize==0)
{
- if(p->oiflag[ OCOL_MEDIAN ]) pp->oi[ OCOL_MEDIAN ] = NAN;
- if(p->oiflag[ OCOL_MAXIMUM ]) pp->oi[ OCOL_MAXIMUM ] = NAN;
- if(p->oiflag[ OCOL_HALFMAXSUM ]) pp->oi[ OCOL_HALFMAXSUM ] = NAN;
- if(p->oiflag[ OCOL_HALFMAXNUM ]) pp->oi[ OCOL_HALFMAXNUM ] = 0;
- if(p->oiflag[ OCOL_HALFSUMNUM ]) pp->oi[ OCOL_HALFSUMNUM ] = 0;
- if(p->oiflag[ OCOL_FRACMAX1NUM ]) pp->oi[ OCOL_FRACMAX1NUM ] = 0;
- if(p->oiflag[ OCOL_FRACMAX2NUM ]) pp->oi[ OCOL_FRACMAX2NUM ] = 0;
- if(p->oiflag[ OCOL_SIGCLIPNUM ]) pp->oi[ OCOL_SIGCLIPNUM ] = 0;
- if(p->oiflag[ OCOL_SIGCLIPSTD ]) pp->oi[ OCOL_SIGCLIPSTD ] = 0;
- if(p->oiflag[ OCOL_SIGCLIPMEAN ]) pp->oi[ OCOL_SIGCLIPMEAN ] = NAN;
- if(p->oiflag[ OCOL_SIGCLIPMEDIAN ]) pp->oi[ OCOL_SIGCLIPMEDIAN] = NAN;
+ if(p->oiflag[OCOL_MEDIAN ]) pp->oi[ OCOL_MEDIAN ] = NAN;
+ if(p->oiflag[OCOL_MAXIMUM ]) pp->oi[ OCOL_MAXIMUM ] = NAN;
+ if(p->oiflag[OCOL_HALFMAXSUM ]) pp->oi[ OCOL_HALFMAXSUM ] = NAN;
+ if(p->oiflag[OCOL_HALFMAXNUM ]) pp->oi[ OCOL_HALFMAXNUM ] = 0;
+ if(p->oiflag[OCOL_HALFSUMNUM ]) pp->oi[ OCOL_HALFSUMNUM ] = 0;
+ if(p->oiflag[OCOL_FRACMAX1NUM ]) pp->oi[ OCOL_FRACMAX1NUM ] = 0;
+ if(p->oiflag[OCOL_FRACMAX2NUM ]) pp->oi[ OCOL_FRACMAX2NUM ] = 0;
+ if(p->oiflag[OCOL_SIGCLIPNUM ]) pp->oi[ OCOL_SIGCLIPNUM ] = 0;
+ if(p->oiflag[OCOL_SIGCLIPSTD ]) pp->oi[ OCOL_SIGCLIPSTD ] = 0;
+ if(p->oiflag[OCOL_SIGCLIPMEAN ]) pp->oi[ OCOL_SIGCLIPMEAN ] = NAN;
+ if(p->oiflag[OCOL_SIGCLIPMEDIAN]) pp->oi[ OCOL_SIGCLIPMEDIAN] = NAN;
if(p->clumps)
for(i=0;i<pp->clumpsinobj;++i)
{
ci=&pp->ci[ i * CCOL_NUMCOLS ];
- if(p->ciflag[ CCOL_MEDIAN ]) ci[ CCOL_MEDIAN ] = NAN;
- if(p->ciflag[ CCOL_MAXIMUM ]) ci[ CCOL_MAXIMUM ] = NAN;
- if(p->ciflag[ CCOL_HALFMAXSUM ]) ci[ CCOL_HALFMAXSUM ] = NAN;
- if(p->ciflag[ CCOL_HALFMAXNUM ]) ci[ CCOL_HALFMAXNUM ] = 0;
- if(p->ciflag[ CCOL_HALFSUMNUM ]) ci[ CCOL_HALFSUMNUM ] = 0;
- if(p->ciflag[ CCOL_FRACMAX1NUM ]) ci[ CCOL_FRACMAX1NUM ] = 0;
- if(p->ciflag[ CCOL_FRACMAX2NUM ]) ci[ CCOL_FRACMAX2NUM ] = 0;
- if(p->ciflag[ CCOL_SIGCLIPNUM ]) ci[ CCOL_SIGCLIPNUM ] = 0;
- if(p->ciflag[ CCOL_SIGCLIPSTD ]) ci[ CCOL_SIGCLIPSTD ] = 0;
- if(p->ciflag[ CCOL_SIGCLIPMEAN ]) ci[ CCOL_SIGCLIPMEAN ] = NAN;
- if(p->ciflag[ CCOL_SIGCLIPMEDIAN ]) ci[ CCOL_SIGCLIPMEDIAN] = NAN;
+ if(p->ciflag[CCOL_MEDIAN ]) ci[ CCOL_MEDIAN ] = NAN;
+ if(p->ciflag[CCOL_MAXIMUM ]) ci[ CCOL_MAXIMUM ] = NAN;
+ if(p->ciflag[CCOL_HALFMAXSUM ]) ci[ CCOL_HALFMAXSUM ] = NAN;
+ if(p->ciflag[CCOL_HALFMAXNUM ]) ci[ CCOL_HALFMAXNUM ] = 0;
+ if(p->ciflag[CCOL_HALFSUMNUM ]) ci[ CCOL_HALFSUMNUM ] = 0;
+ if(p->ciflag[CCOL_FRACMAX1NUM]) ci[ CCOL_FRACMAX1NUM ] = 0;
+ if(p->ciflag[CCOL_FRACMAX2NUM]) ci[ CCOL_FRACMAX2NUM ] = 0;
+ if(p->ciflag[CCOL_SIGCLIPNUM ]) ci[ CCOL_SIGCLIPNUM ] = 0;
+ if(p->ciflag[CCOL_SIGCLIPSTD ]) ci[ CCOL_SIGCLIPSTD ] = 0;
+ if(p->ciflag[CCOL_SIGCLIPMEAN]) ci[ CCOL_SIGCLIPMEAN ] = NAN;
+ if(p->ciflag[CCOL_SIGCLIPMEDIAN]) ci[ CCOL_SIGCLIPMEDIAN]=NAN;
}
return;
}
@@ -1404,8 +1318,8 @@ parse_order_based(struct mkcatalog_passparams *pp)
errno=0;
clumpsvals=malloc(pp->clumpsinobj * sizeof *clumpsvals);
if(clumpsvals==NULL)
- error(EXIT_FAILURE, errno, "%s: couldn't allocate 'clumpsvals' for "
- "%zu clumps", __func__, pp->clumpsinobj);
+ error(EXIT_FAILURE, errno, "%s: couldn't allocate 'clumpsvals' "
+ "for %zu clumps", __func__, pp->clumpsinobj);
/* Allocate the array necessary to keep the values of each clump. */
ccounter=gal_pointer_allocate(GAL_TYPE_SIZE_T, pp->clumpsinobj, 1,
@@ -1469,7 +1383,8 @@ parse_order_based(struct mkcatalog_passparams *pp)
/* Calculate the necessary values for the objects. */
if(p->oiflag[ OCOL_MEDIAN ])
{
- result=gal_data_copy_to_new_type_free(gal_statistics_median(objvals, 1),
+ result=gal_data_copy_to_new_type_free(gal_statistics_median(objvals,
+ 1),
GAL_TYPE_FLOAT64);
pp->oi[OCOL_MEDIAN]=*((double *)(result->array));
gal_data_free(result);
@@ -1524,9 +1439,11 @@ parse_order_based(struct mkcatalog_passparams *pp)
if(clumpsvals[i])
{
result=gal_statistics_median(clumpsvals[i], 1);
- result=gal_data_copy_to_new_type_free(result,
GAL_TYPE_FLOAT64);
+ result=gal_data_copy_to_new_type_free(result,
+ GAL_TYPE_FLOAT64);
ci[ CCOL_MEDIAN ] = ( *((double *)(result->array))
- - (ci[ CCOL_RIV_SUM ]/ci[ CCOL_RIV_NUM
]) );
+ - ( ci[ CCOL_RIV_SUM ]
+ / ci[ CCOL_RIV_NUM ]) );
gal_data_free(result);
}
else ci[ CCOL_MEDIAN ] = NAN;
@@ -1540,28 +1457,36 @@ parse_order_based(struct mkcatalog_passparams *pp)
{
if(clumpsvals[i])
{
- result=gal_statistics_sigma_clip(clumpsvals[i],
p->sigmaclip[0],
+ result=gal_statistics_sigma_clip(clumpsvals[i],
+ p->sigmaclip[0],
p->sigmaclip[1], 1, 1);
sigcliparr=result->array;
if(p->ciflag[ CCOL_SIGCLIPNUM ])
ci[CCOL_SIGCLIPNUM]=sigcliparr[0];
if(p->ciflag[ CCOL_SIGCLIPSTD ])
ci[CCOL_SIGCLIPSTD]=( sigcliparr[3]
- - (ci[ CCOL_RIV_SUM ]/ci[
CCOL_RIV_NUM ]));
+ - ( ci[ CCOL_RIV_SUM ]
+ / ci[ CCOL_RIV_NUM ]));
if(p->ciflag[ CCOL_SIGCLIPMEAN ])
ci[CCOL_SIGCLIPMEAN]=( sigcliparr[2]
- - (ci[ CCOL_RIV_SUM ]/ci[
CCOL_RIV_NUM ]));
+ - ( ci[ CCOL_RIV_SUM ]
+ / ci[ CCOL_RIV_NUM ]));
if(p->ciflag[ CCOL_SIGCLIPMEDIAN ])
ci[CCOL_SIGCLIPMEDIAN]=( sigcliparr[1]
- - (ci[ CCOL_RIV_SUM ]/ci[
CCOL_RIV_NUM ]));
+ - ( ci[ CCOL_RIV_SUM ]
+ / ci[ CCOL_RIV_NUM ]));
gal_data_free(result);
}
else
{
- if(p->ciflag[ CCOL_SIGCLIPNUM ]) ci[ CCOL_SIGCLIPNUM
]=NAN;
- if(p->ciflag[ CCOL_SIGCLIPSTD ]) ci[ CCOL_SIGCLIPSTD
]=NAN;
- if(p->ciflag[ CCOL_SIGCLIPMEAN ]) ci[ CCOL_SIGCLIPMEAN
]=NAN;
- if(p->ciflag[ CCOL_SIGCLIPMEDIAN ])
ci[CCOL_SIGCLIPMEDIAN]=NAN;
+ if(p->ciflag[ CCOL_SIGCLIPNUM ])
+ ci[ CCOL_SIGCLIPNUM ]=NAN;
+ if(p->ciflag[ CCOL_SIGCLIPSTD ])
+ ci[ CCOL_SIGCLIPSTD ]=NAN;
+ if(p->ciflag[ CCOL_SIGCLIPMEAN ])
+ ci[ CCOL_SIGCLIPMEAN ]=NAN;
+ if(p->ciflag[ CCOL_SIGCLIPMEDIAN ])
+ ci[CCOL_SIGCLIPMEDIAN]=NAN;
}
}
@@ -1579,14 +1504,14 @@ parse_order_based(struct mkcatalog_passparams *pp)
parse_area_of_frac_sum(pp, clumpsvals[i], ci, 0);
else
{
- if( p->ciflag[ CCOL_MAXIMUM ]) ci[ CCOL_MAXIMUM
]=NAN;
- if( p->ciflag[ CCOL_HALFMAXNUM ]) ci[ CCOL_HALFMAXNUM
]=NAN;
- if( p->ciflag[ CCOL_HALFMAXSUM ]) ci[ CCOL_HALFMAXSUM
]=NAN;
- if( p->ciflag[ CCOL_HALFSUMNUM ]) ci[ CCOL_HALFSUMNUM
]=NAN;
- if( p->ciflag[ CCOL_FRACMAX1NUM ]) ci[ CCOL_FRACMAX1NUM
]=NAN;
- if( p->ciflag[ CCOL_FRACMAX1SUM ]) ci[ CCOL_FRACMAX1SUM
]=NAN;
- if( p->ciflag[ CCOL_FRACMAX2NUM ]) ci[ CCOL_FRACMAX2NUM
]=NAN;
- if( p->ciflag[ CCOL_FRACMAX2SUM ]) ci[ CCOL_FRACMAX2SUM
]=NAN;
+ if(p->ciflag[CCOL_MAXIMUM ]) ci[CCOL_MAXIMUM ]=NAN;
+ if(p->ciflag[CCOL_HALFMAXNUM ]) ci[CCOL_HALFMAXNUM ]=NAN;
+ if(p->ciflag[CCOL_HALFMAXSUM ]) ci[CCOL_HALFMAXSUM ]=NAN;
+ if(p->ciflag[CCOL_HALFSUMNUM ]) ci[CCOL_HALFSUMNUM ]=NAN;
+ if(p->ciflag[CCOL_FRACMAX1NUM]) ci[CCOL_FRACMAX1NUM]=NAN;
+ if(p->ciflag[CCOL_FRACMAX1SUM]) ci[CCOL_FRACMAX1SUM]=NAN;
+ if(p->ciflag[CCOL_FRACMAX2NUM]) ci[CCOL_FRACMAX2NUM]=NAN;
+ if(p->ciflag[CCOL_FRACMAX2SUM]) ci[CCOL_FRACMAX2SUM]=NAN;
}
}
diff --git a/bin/mkcatalog/ui.c b/bin/mkcatalog/ui.c
index caacf661..b08c47c0 100644
--- a/bin/mkcatalog/ui.c
+++ b/bin/mkcatalog/ui.c
@@ -227,15 +227,14 @@ ui_column_codes_ll(struct argp_option *option, char *arg,
if( arg[0]=='0' && arg[1]=='\0' ) return NULL;
else if ( !(arg[0]=='1' && arg[1]=='\0') )
error_at_line(EXIT_FAILURE, 0, filename, lineno, "'%s' is not a "
- "valid value to the '%s' option: ('%s').\n\n'%s' is "
- "an on/off option specifying if you want this column "
- "in the output catalog, it doesn't take any "
- "arguments. In a configuration file, it can only take "
- "a value of '0' (to be ignored) or '1'", arg,
+ "valid value to the '%s' option: ('%s').\n\n'%s' "
+ "is an on/off option specifying if you want this "
+ "column in the output catalog, it doesn't take any "
+ "arguments. In a configuration file, it can only "
+ "take a value of '0' (to be ignored) or '1'", arg,
option->name, option->doc, option->name);
}
-
/* The user wants this column, so add it to the list. Note that the 'ids'
column means three columns. */
if(option->key==UI_KEY_IDS)
@@ -318,8 +317,8 @@ ui_check_upperlimit(struct argp_option *option, char *arg,
error_at_line(EXIT_FAILURE, 0, filename, lineno, "%g (value "
"number %zu given to '--%s') is not an "
"integer. The value(s) to this option are "
- "object/clump labels/identifiers, so they must be "
- "integers", d[i], i+1, option->name);
+ "object/clump labels/identifiers, so they must "
+ "be integers", d[i], i+1, option->name);
if( d[i]<=0 )
error_at_line(EXIT_FAILURE, 0, filename, lineno, "%g (value "
"number %zu given to '--%s') is not positive. "
@@ -378,10 +377,10 @@ ui_read_check_only_options(struct mkcatalogparams *p)
error(EXIT_FAILURE, 0, "no clumps catalog is requested, hence "
"'--checkuplim' is only available for objects (one value "
"must be given to it).\n\n"
- "To ask for a clumps catalog, please append '--clumpscat' to the "
- "command calling MakeCatalog.\n\n"
- "If you want the upperlimit check table for an object, only give "
- "one value (the object's label) to '--checkuplim'.");
+ "To ask for a clumps catalog, please append '--clumpscat' to "
+ "the command calling MakeCatalog.\n\n"
+ "If you want the upperlimit check table for an object, only "
+ "give one value (the object's label) to '--checkuplim'.");
/* See if '--skyin' is a filename or a value. When the string is ONLY a
number (and nothing else), 'tailptr' will point to the end of the
@@ -392,8 +391,8 @@ ui_read_check_only_options(struct mkcatalogparams *p)
if(*tailptr=='\0')
{
/* Allocate the data structure. */
- p->sky=gal_data_alloc(NULL, GAL_TYPE_FLOAT32, 1, &one, NULL, 0, -1,
- 1, NULL, NULL, NULL);
+ p->sky=gal_data_alloc(NULL, GAL_TYPE_FLOAT32, 1, &one, NULL,
+ 0, -1, 1, NULL, NULL, NULL);
/* Write the value inside it. */
*((float *)(p->sky->array))=tmp;
@@ -407,8 +406,8 @@ ui_read_check_only_options(struct mkcatalogparams *p)
if(*tailptr=='\0')
{
/* Allocate the data structure. */
- p->std=gal_data_alloc(NULL, GAL_TYPE_FLOAT32, 1, &one, NULL, 0, -1,
- 1, NULL, NULL, NULL);
+ p->std=gal_data_alloc(NULL, GAL_TYPE_FLOAT32, 1, &one, NULL,
+ 0, -1, 1, NULL, NULL, NULL);
/* Write the value inside it. */
*((float *)(p->std->array))=tmp;
@@ -459,10 +458,11 @@ ui_check_options_and_arguments(struct mkcatalogparams *p)
if(p->objectsfile)
{
if( gal_fits_file_recognized(p->objectsfile) && p->cp.hdu==NULL )
- error(EXIT_FAILURE, 0, "no HDU specified. When the input is a FITS "
- "file, a HDU must also be specified, you can use the '--hdu' "
- "('-h') option and give it the HDU number (starting from "
- "zero), extension name, or anything acceptable by CFITSIO");
+ error(EXIT_FAILURE, 0, "no HDU specified. When the input is a "
+ "FITS file, a HDU must also be specified, you can use the "
+ "'--hdu' ('-h') option and give it the HDU number (starting "
+ "from zero), extension name, or anything acceptable by "
+ "CFITSIO");
}
else
@@ -500,13 +500,13 @@ ui_set_filenames(struct mkcatalogparams *p)
p->usedvaluesfile = p->valuesfile ? p->valuesfile : p->objectsfile;
- p->usedskyfile = ( p->skyfile
- ? p->skyfile
- : ( p->valuesfile ? p->valuesfile : p->objectsfile ) );
+ p->usedskyfile = ( p->skyfile
+ ? p->skyfile
+ : (p->valuesfile ? p->valuesfile : p->objectsfile) );
- p->usedstdfile = ( p->stdfile
- ? p->stdfile
- : ( p->valuesfile ? p->valuesfile : p->objectsfile ) );
+ p->usedstdfile = ( p->stdfile
+ ? p->stdfile
+ : (p->valuesfile ? p->valuesfile : p->objectsfile) );
}
@@ -560,10 +560,11 @@ ui_wcs_info(struct mkcatalogparams *p)
for(i=0;i<p->objects->ndim;++i)
{
/* CTYPE might contain '-' characters, we just want the first
- non-dash characters. The loop will either stop either at the end
- or where there is a dash. So we can just replace it with an
- end-of-string character. */
- gal_checkset_allocate_copy(p->objects->wcs->ctype[i], &p->ctype[i]);
+ non-dash characters. The loop will either stop either at the
+ end or where there is a dash. So we can just replace it with
+ an end-of-string character. */
+ gal_checkset_allocate_copy(p->objects->wcs->ctype[i],
+ &p->ctype[i]);
c=p->ctype[i]; while(*c!='\0' && *c!='-') ++c;
*c='\0';
}
@@ -584,7 +585,8 @@ ui_num_clumps(struct mkcatalogparams *p)
gal_list_i32_t *tmp, **labsinobj;
int32_t *o=p->objects->array, *of=o+p->objects->size, *c=p->clumps->array;
- /* Allocate array of lists to keep the unique labels within each object. */
+ /* Allocate array of lists to keep the unique labels within each
+ object. */
errno=0;
labsinobj=calloc(p->numobjects+1, sizeof *labsinobj);
if(labsinobj==NULL)
@@ -600,7 +602,8 @@ ui_num_clumps(struct mkcatalogparams *p)
{
/* See if the label has already been found. */
olab = p->outlabsinv ? p->outlabsinv[*o] : *o;
- for(tmp=labsinobj[olab];tmp!=NULL;tmp=tmp->next) if(tmp->v==*c)
break;
+ for(tmp=labsinobj[olab];tmp!=NULL;tmp=tmp->next)
+ if(tmp->v==*c) break;
/* When it wasn't found, 'tmp==NULL'. */
if(tmp==NULL)
@@ -835,6 +838,7 @@ ui_one_tile_per_object_correct_numobjects(struct
mkcatalogparams *p)
static void
ui_read_labels(struct mkcatalogparams *p)
{
+ gal_list_i32_t *colcode;
gal_data_t *tmp, *keys=gal_data_array_calloc(2);
/* Read it into memory. */
@@ -859,11 +863,24 @@ ui_read_labels(struct mkcatalogparams *p)
p->cp.hdu, p->objects->ndim);
- /* Make sure the '--spectrum' option is not given on a 2D image. */
- if(p->spectrum && p->objects->ndim!=3)
- error(EXIT_FAILURE, 0, "%s (hdu %s) has %zu dimensions, but '--spectrum' "
- "is currently only defined on 3D datasets", p->objectsfile,
- p->cp.hdu, p->objects->ndim);
+ /* If a column needs a 3D input, do the check here. */
+ for(colcode=p->columnids; colcode!=NULL; colcode=colcode->next)
+ switch(colcode->v)
+ {
+ case UI_KEY_SUMINSLICE: case UI_KEY_SUMERRINSLICE:
+ case UI_KEY_AREAINSLICE: case UI_KEY_SUMPROJINSLICE:
+ case UI_KEY_AREAPROJINSLICE: case UI_KEY_SUMPROJERRINSLICE:
+ case UI_KEY_AREAOTHERINSLICE: case UI_KEY_SUMOTHERINSLICE:
+ case UI_KEY_SUMOTHERERRINSLICE:
+ if(p->objects->ndim!=3)
+ error(EXIT_FAILURE, 0, "%s (hdu %s) has %zu dimensions, but "
+ "at least one requested column requires a 3D input "
+ "(for example those ending with 'inslice', they are "
+ "clearly marked with '[3D input]' in the output of "
+ "'%s --help')", p->objectsfile, p->cp.hdu,
+ p->objects->ndim, PROGRAM_EXEC);
+ break;
+ }
/* See if the total number of objects is given in the header keywords. */
@@ -874,7 +891,7 @@ ui_read_labels(struct mkcatalogparams *p)
if(keys[0].status) /* status!=0: the key couldn't be read by CFITSIO. */
{
tmp=gal_statistics_maximum(p->objects);
- p->numobjects=*((int32_t *)(tmp->array)); /*numobjects is in int32_t.*/
+ p->numobjects=*((int32_t *)(tmp->array)); /*numobjects is int32_t.*/
gal_data_free(tmp);
}
@@ -883,8 +900,8 @@ ui_read_labels(struct mkcatalogparams *p)
error (it is pointless to build a catalog). */
if(p->numobjects==0)
error(EXIT_FAILURE, 0, "no object labels (non-zero pixels) in "
- "%s (hdu %s). To make a catalog, labeled regions must be defined",
- p->objectsfile, p->cp.hdu);
+ "%s (hdu %s). To make a catalog, labeled regions must be "
+ "defined", p->objectsfile, p->cp.hdu);
/* See if the labels image has blank pixels and set the flags
@@ -911,8 +928,8 @@ ui_read_labels(struct mkcatalogparams *p)
"give a specific HDU using its number (counting from zero) "
"or name. If the dataset is in another file, please use "
"'--clumpsfile' to give the filename. If you don't want any "
- "clumps catalog output, remove the '--clumpscat' option from "
- "the command-line or give it a value of zero in a "
+ "clumps catalog output, remove the '--clumpscat' option "
+ "from the command-line or give it a value of zero in a "
"configuration file", p->usedclumpsfile);
/* Read the clumps image. */
@@ -955,11 +972,11 @@ ui_read_labels(struct mkcatalogparams *p)
error(EXIT_FAILURE, 0, "%s (hdu: %s): the 'NUMCLUMPS' header "
"keyword has a value of zero, but there are positive "
"pixels in the array, showing that there are clumps in "
- "image. This is a wrong usage of the 'NUMCLUMPS' keyword."
- "It must contain the total number of clumps (irrespective "
- "of how many objects there are). Please correct this issue "
- "and run MakeCatalog again", p->usedclumpsfile,
- p->clumpshdu);
+ "image. This is a wrong usage of the 'NUMCLUMPS' "
+ "keyword. It must contain the total number of clumps "
+ "(irrespective of how many objects there are). Please "
+ "correct this issue and run MakeCatalog again",
+ p->usedclumpsfile, p->clumpshdu);
/* Since there are no clumps, we won't bother creating a clumps
catalog and from this step onward, we'll act as if no clumps
@@ -997,7 +1014,6 @@ ui_necessary_inputs(struct mkcatalogparams *p, int
*values, int *sky,
/* Set necessary inputs based on options. */
if(p->forcereadstd) *std=1;
if(p->upperlimit) *values=1;
- if(p->spectrum) *values=*std=1;
/* Go over all the object columns. Note that the objects and clumps (if
the '--clumpcat' option is given) inputs are mandatory and it is not
@@ -1066,6 +1082,17 @@ ui_necessary_inputs(struct mkcatalogparams *p, int
*values, int *sky,
case OCOL_C_GZ: /* Only clump labels. */ break;
case OCOL_C_SUMWHT: *values = 1; break;
case OCOL_C_NUMWHT: *values = 1; break;
+ case OCOL_SUMINSLICE: *values = 1; break;
+ case OCOL_NUMINSLICE: *values = 1; break;
+ case OCOL_NUMALLINSLICE: /* Only object labels. */ break;
+ case OCOL_SUMVARINSLICE: *values = *std = 1; break;
+ case OCOL_SUMPROJINSLICE: *values = 1; break;
+ case OCOL_NUMPROJINSLICE: *values = 1; break;
+ case OCOL_NUMOTHERINSLICE: *values = 1; break;
+ case OCOL_SUMOTHERINSLICE: *values = 1; break;
+ case OCOL_SUMPROJVARINSLICE: *values = *std = 1; break;
+ case OCOL_SUMOTHERVARINSLICE: *values = *std = 1; break;
+ case OCOL_NUMALLOTHERINSLICE: /* Only object labels. */ break;
default:
error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at %s to "
"fix the problem. The code %zu is not a recognized "
@@ -1267,7 +1294,8 @@ ui_preparations_read_inputs(struct mkcatalogparams *p)
"give the filename", p->usedvaluesfile);
/* Read the values dataset. */
- p->values=gal_array_read_one_ch_to_type(p->usedvaluesfile, p->valueshdu,
+ p->values=gal_array_read_one_ch_to_type(p->usedvaluesfile,
+ p->valueshdu,
NULL, GAL_TYPE_FLOAT32,
p->cp.minmapsize,
p->cp.quietmmap);
@@ -1291,12 +1319,16 @@ ui_preparations_read_inputs(struct mkcatalogparams *p)
{
for(column=p->objectcols; column!=NULL; column=column->next)
if( !strcmp(column->unit, MKCATALOG_NO_UNIT) )
- { free(column->unit);
- gal_checkset_allocate_copy(p->values->unit, &column->unit); }
+ {
+ free(column->unit);
+ gal_checkset_allocate_copy(p->values->unit, &column->unit);
+ }
for(column=p->clumpcols; column!=NULL; column=column->next)
if( !strcmp(column->unit, MKCATALOG_NO_UNIT) )
- { free(column->unit);
- gal_checkset_allocate_copy(p->values->unit, &column->unit); }
+ {
+ free(column->unit);
+ gal_checkset_allocate_copy(p->values->unit, &column->unit);
+ }
}
}
@@ -1313,10 +1345,10 @@ ui_preparations_read_inputs(struct mkcatalogparams *p)
error(EXIT_FAILURE, 0, "%s: no HDU/extension provided for the "
"SKY dataset. Atleast one column needs this dataset, or "
"you have asked to subtract the Sky from the values.\n\n"
- "Please use the '--skyhdu' option to give a specific HDU "
- "using its number (counting from zero) or name. If the "
- "dataset is in another file, please use '--skyin' to "
- "give the filename", p->usedskyfile);
+ "Please use the '--skyhdu' option to give a specific "
+ "HDU using its number (counting from zero) or name. If "
+ "the dataset is in another file, please use '--skyin' "
+ "to give the filename", p->usedskyfile);
/* Read the Sky dataset. */
p->sky=gal_array_read_one_ch_to_type(p->usedskyfile, p->skyhdu,
@@ -1353,7 +1385,8 @@ ui_preparations_read_inputs(struct mkcatalogparams *p)
/* Read the Sky standard deviation image into memory. */
p->std=gal_array_read_one_ch_to_type(p->usedstdfile, p->stdhdu,
NULL, GAL_TYPE_FLOAT32,
- p->cp.minmapsize, p->cp.quietmmap);
+ p->cp.minmapsize,
+ p->cp.quietmmap);
p->std->ndim=gal_dimension_remove_extra(p->std->ndim,
p->std->dsize, NULL);
@@ -1396,17 +1429,17 @@ ui_preparations_read_inputs(struct mkcatalogparams *p)
/* Check its size. */
if( gal_dimension_is_different(p->objects, p->upmask) )
- error(EXIT_FAILURE, 0, "'%s' (hdu: %s) and '%s' (hdu: %s) have a"
- "different dimension/size", p->upmaskfile, p->upmaskhdu,
- p->objectsfile, p->cp.hdu);
+ error(EXIT_FAILURE, 0, "'%s' (hdu: %s) and '%s' (hdu: %s) "
+ "have a different dimension/size", p->upmaskfile,
+ p->upmaskhdu, p->objectsfile, p->cp.hdu);
/* If it isn't an integer type, report an error. */
if( p->upmask->type==GAL_TYPE_FLOAT32
|| p->upmask->type==GAL_TYPE_FLOAT64 )
error(EXIT_FAILURE, 0, "%s (hdu: %s) has a %s numerical data "
- "type. Only integer type inputs are acceptable as a mask."
- "If the values are indeed integers, only placed in a "
- "floating point container, you can use Gnuastro's "
+ "type. Only integer type inputs are acceptable as a "
+ "mask. If the values are indeed integers, only placed "
+ "in a floating point container, you can use Gnuastro's "
"Arithmetic program to conver the numeric data type",
p->upmaskfile, p->upmaskhdu,
gal_type_name(p->upmask->type, 1));
@@ -1444,9 +1477,9 @@ ui_preparations_read_keywords(struct mkcatalogparams *p)
/* Read the keywords from the standard deviation image. */
keys=gal_data_array_calloc(2);
keys[0].next=&keys[1];
- keys[0].name="MINSTD"; keys[1].name="MEDSTD";
- keys[0].type=GAL_TYPE_FLOAT32; keys[1].type=GAL_TYPE_FLOAT32;
- keys[0].array=&minstd; keys[1].array=&p->medstd;
+ keys[0].name="MINSTD"; keys[1].name="MEDSTD";
+ keys[0].type=GAL_TYPE_FLOAT32; keys[1].type=GAL_TYPE_FLOAT32;
+ keys[0].array=&minstd; keys[1].array=&p->medstd;
gal_fits_key_read(p->usedstdfile, p->stdhdu, keys, 0, 0);
/* If the two keywords couldn't be read. We don't want to slow
@@ -1539,8 +1572,10 @@ ui_preparations_both_names(struct mkcatalogparams *p)
file. */
if(p->cp.tableformat==GAL_TABLE_FORMAT_TXT)
{
- p->objectsout=gal_checkset_automatic_output(&p->cp, basename, "_o.txt");
- p->clumpsout=gal_checkset_automatic_output(&p->cp, basename, "_c.txt");
+ p->objectsout=gal_checkset_automatic_output(&p->cp, basename,
+ "_o.txt");
+ p->clumpsout=gal_checkset_automatic_output(&p->cp, basename,
+ "_c.txt");
}
else
{
@@ -1555,7 +1590,8 @@ ui_preparations_both_names(struct mkcatalogparams *p)
p->cp.dontdelete);
}
else
- p->objectsout=gal_checkset_automatic_output(&p->cp, basename, suffix);
+ p->objectsout=gal_checkset_automatic_output(&p->cp, basename,
+ suffix);
p->clumpsout=p->objectsout;
}
@@ -1607,7 +1643,8 @@ ui_preparations_outnames(struct mkcatalogparams *p)
{
suffix = ( p->cp.tableformat==GAL_TABLE_FORMAT_TXT
? "_cat.txt" : "_cat.fits" );
- p->objectsout=gal_checkset_automatic_output(&p->cp, p->objectsfile,
+ p->objectsout=gal_checkset_automatic_output(&p->cp,
+ p->objectsfile,
suffix);
}
}
@@ -1643,91 +1680,6 @@ ui_preparations_outnames(struct mkcatalogparams *p)
-/* When a spectrum is requested, the slice information (slice number and
- slice WCS) is common to all different spectra. So instead of calculating
- it every time, we'll just make it once here, then copy it for every
- object.
-
- The Slice information is going to be written in every spectrum. So we
- don't want it to take too much space. Therefore, only when the number of
- slices is less than 65535 (2^16-1), will we actually use a 32-bit
- integer type for the slice number column.
-*/
-static void
-ui_preparations_spectrum_wcs(struct mkcatalogparams *p)
-{
- double *xarr, *yarr, *zarr;
- gal_data_t *x, *y, *z, *coords;
- size_t i, numslices=p->objects->dsize[0];
- size_t slicenumtype=numslices>=65535 ? GAL_TYPE_UINT32 : GAL_TYPE_UINT16;
-
- /* A small sanity check. */
- if(p->objects->ndim!=3)
- error(EXIT_FAILURE, 0, "%s (hdu %s) is a %zuD dataset, but '--spectrum' "
- "is currently only defined on 3D datasets", p->objectsfile,
- p->cp.hdu, p->objects->ndim);
-
- /* Allocate space for the slice number as well as the X and Y positions
- for WCS conversion. Note that the 'z' axis is going to be converted to
- WCS later, so we'll just give it the basic information now.*/
- x=gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 0,
- p->cp.minmapsize, p->cp.quietmmap, NULL, NULL, NULL);
- y=gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 0,
- p->cp.minmapsize, p->cp.quietmmap, NULL, NULL, NULL);
- z=gal_data_alloc(NULL, GAL_TYPE_FLOAT64, 1, &numslices, NULL, 0,
- p->cp.minmapsize, p->cp.quietmmap, p->ctype[2],
- p->objects->wcs->cunit[2], "Slice WCS coordinates.");
-
- /* Write values into the 3 coordinates. */
- xarr=x->array; yarr=y->array; zarr=z->array;
- for(i=0;i<numslices;++i) { zarr[i]=i+1; xarr[i]=yarr[i]=1; }
-
-
- /* Convert the coordinates to WCS. We are doing this inplace to avoid too
- much memory/speed consumption. */
- coords=x;
- coords->next=y;
- coords->next->next=z;
- gal_wcs_img_to_world(coords, p->objects->wcs, 1);
-
- /* For a check.
- for(i=0;i<numslices;++i)
- printf("%g, %g, %g\n", xarr[i], yarr[i], zarr[i]);
- exit(0);
- */
-
- /* Allocate the slice counter array (we are doing it again because we
- want it to be in integer type now). */
- p->specsliceinfo=gal_data_alloc(NULL, slicenumtype, 1, &numslices, NULL, 0,
- p->cp.minmapsize, p->cp.quietmmap, "SLICE",
- "counter",
- "Slice number in cube (counting from 1).");
- if(p->specsliceinfo->type==GAL_TYPE_UINT16)
- for(i=0;i<numslices;++i) ((uint16_t *)(p->specsliceinfo->array))[i]=i+1;
- else
- for(i=0;i<numslices;++i) ((uint32_t *)(p->specsliceinfo->array))[i]=i+1;
-
- /* Set the slice WCS column information. Note that 'z' is now the WCS
- coordinate value of the third dimension, and to avoid wasting extra
- space (this column is repeated one very object's spectrum), we'll
- convert it to a 32-bit floating point dataset. */
- p->specsliceinfo->next=gal_data_copy_to_new_type(z, GAL_TYPE_FLOAT32);
-
- /* For a final check.
- gal_table_write(p->specsliceinfo, NULL, NULL, GAL_TABLE_FORMAT_BFITS,
- "specsliceinfo.fits", "test-debug", 0);
- */
-
- /* Clean up. */
- gal_data_free(x);
- gal_data_free(y);
- gal_data_free(z);
-}
-
-
-
-
-
/* Sanity checks and preparations for the upper-limit magnitude. */
static void
ui_preparations_upperlimit(struct mkcatalogparams *p)
@@ -1740,8 +1692,8 @@ ui_preparations_upperlimit(struct mkcatalogparams *p)
{
for(i=0;p->uprange[i]!=-1;++i) ++c;
if(c!=p->objects->ndim)
- error(EXIT_FAILURE, 0, "%zu values given to '--uprange', but input "
- "has %zu dimensions", c, p->objects->ndim);
+ error(EXIT_FAILURE, 0, "%zu values given to '--uprange', but "
+ "input has %zu dimensions", c, p->objects->ndim);
}
/* Check the number of random samples. */
@@ -1786,7 +1738,7 @@ void
ui_preparations(struct mkcatalogparams *p)
{
/* If no columns are requested, then inform the user. */
- if(p->columnids==NULL && p->spectrum==0)
+ if(p->columnids==NULL)
error(EXIT_FAILURE, 0, "no measurements requested! Please run again "
"with '--help' for the possible list of measurements");
@@ -1816,14 +1768,6 @@ ui_preparations(struct mkcatalogparams *p)
ui_preparations_outnames(p);
- /* If a spectrum is requested, generate the two WCS columns. */
- if(p->spectrum)
- {
- ui_preparations_spectrum_wcs(p);
- p->spectra=gal_data_array_calloc(p->numobjects);
- }
-
-
/* Allocate the reference random number generator and seed values. It
will be cloned once for every thread. If the user hasn't called
'envseed', then we want it to be different for every run, so we need
@@ -1875,7 +1819,8 @@ ui_preparations(struct mkcatalogparams *p)
/**************************************************************/
void
-ui_read_check_inputs_setup(int argc, char *argv[], struct mkcatalogparams *p)
+ui_read_check_inputs_setup(int argc, char *argv[],
+ struct mkcatalogparams *p)
{
char *tmp;
struct gal_options_common_params *cp=&p->cp;
@@ -1960,7 +1905,8 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct
mkcatalogparams *p)
else
printf(" - Sky: %s (hdu: %s)\n", p->usedskyfile, p->skyhdu);
if(p->subtractsky)
- printf(" - Sky has been subtracted from values internally.\n");
+ printf(" - Sky has been subtracted from values "
+ "internally.\n");
}
if(p->std)
@@ -2010,7 +1956,7 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct
mkcatalogparams *p)
void
ui_free_report(struct mkcatalogparams *p, struct timeval *t1)
{
- size_t d, i;
+ size_t d;
/* The temporary arrays for WCS coordinates. */
if(p->wcs_vo ) gal_list_data_free(p->wcs_vo);
@@ -2059,27 +2005,10 @@ ui_free_report(struct mkcatalogparams *p, struct
timeval *t1)
if(p->outlabs) free(p->outlabs);
gal_list_data_free(p->clumpcols);
gal_list_data_free(p->objectcols);
- gal_list_data_free(p->specsliceinfo);
if(p->outlabsinv) free(p->outlabsinv);
if(p->upcheckout) free(p->upcheckout);
gal_data_array_free(p->tiles, p->numobjects, 0);
- /* Clean up the spectra. */
- if(p->spectra)
- {
- /* Note that each element of the array is the first node in a list of
- datasets. So we can't free the first one with
- 'gal_list_data_free', we'll delete all the nodes after it in the
- loop. */
- for(i=0;i<p->numobjects;++i)
- {
- gal_list_data_free( p->spectra[i].next );
- p->spectra[i].next=NULL;
- gal_data_free_contents(&p->spectra[i]);
- }
- gal_data_array_free(p->spectra, p->numobjects, 0);
- }
-
/* If the Sky or its STD image were given in tiles, then we defined a
tile structure to deal with them. The initialization of the tile
structure is checked with its 'ndim' element. */
diff --git a/bin/mkcatalog/ui.h b/bin/mkcatalog/ui.h
index 5028db01..c28bda7a 100644
--- a/bin/mkcatalog/ui.h
+++ b/bin/mkcatalog/ui.h
@@ -42,6 +42,7 @@ enum program_args_groups
UI_GROUP_COLUMNS_SURFACEBRIGHTNESS,
UI_GROUP_COLUMNS_MORPHOLOGY,
UI_GROUP_COLUMNS_ELLIPTICAL,
+ UI_GROUP_COLUMNS_VECTOR,
};
@@ -197,6 +198,17 @@ enum option_keys_enum
UI_KEY_FRACMAX2AREA,
UI_KEY_FRACMAX1RADIUS,
UI_KEY_FRACMAX2RADIUS,
+
+ /* Vector columns */
+ UI_KEY_SUMINSLICE,
+ UI_KEY_SUMERRINSLICE,
+ UI_KEY_AREAINSLICE,
+ UI_KEY_SUMPROJINSLICE,
+ UI_KEY_AREAPROJINSLICE,
+ UI_KEY_SUMPROJERRINSLICE,
+ UI_KEY_AREAOTHERINSLICE,
+ UI_KEY_SUMOTHERINSLICE,
+ UI_KEY_SUMOTHERERRINSLICE,
};
diff --git a/bin/noisechisel/astnoisechisel-3d.conf
b/bin/noisechisel/astnoisechisel-3d.conf
index eebed947..336478f7 100644
--- a/bin/noisechisel/astnoisechisel-3d.conf
+++ b/bin/noisechisel/astnoisechisel-3d.conf
@@ -24,8 +24,8 @@
# Tessellation
numchannels 1,1,1
- tilesize 15,15,15
- largetilesize 50,50,50
+ tilesize 15,15,5
+ largetilesize 50,50,15
# Detection:
meanmedqdiff 0.005
diff --git a/bin/script/fits-view.in b/bin/script/fits-view.in
index a04e0151..346caa52 100644
--- a/bin/script/fits-view.in
+++ b/bin/script/fits-view.in
@@ -404,11 +404,18 @@ else
# Open DS9 based on the number of dimension.
if [ "$ndim" = 2 ]; then
+ # If a HDU is specified, ignore other HDUs (recall that
+ # with '-mecube' we are viewing all the HDUs as a single
+ # cube.
+ if [ x"$hdu" = x ]; then mecube="-mecube";
+ else mecube="";
+ fi
+
# 2D multi-extension file: use the "Cube" window to
# flip/slide through the extensions.
execom="$ds9exec $ds9scaleopt \
$ds9geoopt \
- -mecube \
+ $mecube \
$inwithhdu \
-zoom to fit \
-wcs degrees \
@@ -423,6 +430,11 @@ else
$ds9extra"
else
+ # If a HDU is given, don't use multi-frame.
+ if [ x"$hdu" = x ]; then mframe="-multiframe";
+ else mframe="";
+ fi
+
# 3D multi-extension file: The "Cube" window will slide
# between the slices of a single extension. To flip through
# the extensions (not the slices), press the top row
@@ -432,7 +444,7 @@ else
# the same slice).
execom="$ds9exec $ds9scaleopt \
$ds9geoopt -wcs degrees \
- -multiframe \
+ $mframe \
$inwithhdu \
-lock slice image \
-lock frame image \
diff --git a/bin/segment/astsegment-3d.conf b/bin/segment/astsegment-3d.conf
index 4c949995..402f9d8a 100644
--- a/bin/segment/astsegment-3d.conf
+++ b/bin/segment/astsegment-3d.conf
@@ -28,8 +28,8 @@
# Tessellation
numchannels 1,1,1
- tilesize 15,15,15
- largetilesize 50,50,50
+ tilesize 15,15,5
+ largetilesize 50,50,15
# Segmentation
snminarea 15
diff --git a/bin/statistics/ui.c b/bin/statistics/ui.c
index 8f1a7cc5..d2b618b1 100644
--- a/bin/statistics/ui.c
+++ b/bin/statistics/ui.c
@@ -853,7 +853,7 @@ ui_read_columns_in_one(struct statisticsparams *p)
/* Read the different comma-separated strings into an array (within a
'gal_data_t'). */
- strs=gal_options_parse_csv_strings_raw(tmp->v, NULL, 0);
+ strs=gal_options_parse_csv_strings_to_data(tmp->v, NULL, 0);
strarr=strs->array;
/* Add each array element to the final list of columns. */
diff --git a/bin/table/args.h b/bin/table/args.h
index 4c84c765..03150a60 100644
--- a/bin/table/args.h
+++ b/bin/table/args.h
@@ -42,7 +42,8 @@ struct argp_option program_options[] =
GAL_TYPE_STRLL,
GAL_OPTIONS_RANGE_ANY,
GAL_OPTIONS_NOT_MANDATORY,
- GAL_OPTIONS_NOT_SET
+ GAL_OPTIONS_NOT_SET,
+ gal_options_parse_csv_strings_append
},
{
"wcsfile",
@@ -237,6 +238,30 @@ struct argp_option program_options[] =
+ /* Operation precendence */
+ {
+ 0, 0, 0, 0,
+ "Precedence (default: column operations first)",
+ UI_GROUP_PRECEDENCE
+ },
+ {
+ "rowfirst",
+ UI_KEY_ROWFIRST,
+ 0,
+ 0,
+ "Apply row-based operations first.",
+ UI_GROUP_PRECEDENCE,
+ &p->rowfirst,
+ GAL_OPTIONS_NO_ARG_TYPE,
+ GAL_OPTIONS_RANGE_0_OR_1,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET
+ },
+
+
+
+
+
/* Output columns. */
{
0, 0, 0, 0,
@@ -259,9 +284,9 @@ struct argp_option program_options[] =
{
"colmetadata",
UI_KEY_COLMETADATA,
- "STR,STR[,STR,STR]",
+ "ID,S,S,S",
0,
- "Column metadata (name, unit, comments).",
+ "Column metadata (S=STR: Name, Unit, Comments).",
UI_GROUP_OUTCOLS,
&p->colmetadata,
GAL_TYPE_STRING,
@@ -310,7 +335,19 @@ struct argp_option program_options[] =
GAL_OPTIONS_NOT_MANDATORY,
GAL_OPTIONS_NOT_SET
},
-
+ {
+ "transpose",
+ UI_KEY_TRANSPOSE,
+ 0,
+ 0,
+ "Transpose table (must only contain vector cols).",
+ UI_GROUP_OUTCOLS,
+ &p->transpose,
+ GAL_OPTIONS_NO_ARG_TYPE,
+ GAL_OPTIONS_RANGE_0_OR_1,
+ GAL_OPTIONS_NOT_MANDATORY,
+ GAL_OPTIONS_NOT_SET
+ },
diff --git a/bin/table/arithmetic.c b/bin/table/arithmetic.c
index 5885f871..edb323c0 100644
--- a/bin/table/arithmetic.c
+++ b/bin/table/arithmetic.c
@@ -37,6 +37,8 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <gnuastro-internal/arithmetic-set.h>
#include "main.h"
+
+#include "ui.h"
#include "arithmetic.h"
@@ -375,7 +377,7 @@ arithmetic_indexs_final(struct tableparams *p)
p->colarray=gal_list_data_to_array_ptr(p->table, &p->numcolarray);
/* go over each package of columns. */
- for(tmp=p->outcols;tmp!=NULL;tmp=tmp->next)
+ for(tmp=p->colpack;tmp!=NULL;tmp=tmp->next)
{
/* If we are on an arithmetic operation. */
if(tmp->arith)
@@ -1240,7 +1242,7 @@ arithmetic_operate(struct tableparams *p)
p->table=NULL;
/* Go over each package of columns. */
- for(outpack=p->outcols; outpack!=NULL; outpack=outpack->next)
+ for(outpack=p->colpack; outpack!=NULL; outpack=outpack->next)
{
if(outpack->arith)
arithmetic_reverse_polish(p, outpack);
@@ -1255,4 +1257,10 @@ arithmetic_operate(struct tableparams *p)
column contents have either been moved into the new table, or have
already been freed. */
gal_list_data_reverse(&p->table);
+
+ /* Clean up. */
+ ui_colpack_free(p->colpack);
+ if(p->colarray) free(p->colarray);
+ p->colarray=NULL;
+ p->colpack=NULL;
}
diff --git a/bin/table/main.h b/bin/table/main.h
index c0f812a6..8567de01 100644
--- a/bin/table/main.h
+++ b/bin/table/main.h
@@ -76,7 +76,7 @@ struct arithmetic_token
struct arithmetic_token *next; /* Pointer to next token. */
};
-/* */
+/* For arithmetic operations. */
struct column_pack
{
size_t start; /* Starting ind. in requested columns. */
@@ -100,6 +100,7 @@ struct tableparams
gal_list_str_t *columns; /* List of given columns. */
uint8_t information; /* ==1: only print FITS information. */
uint8_t colinfoinstdout; /* ==1: print column metadata in CL. */
+ uint8_t rowfirst; /* Do row-based operations first. */
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. */
@@ -122,6 +123,7 @@ struct tableparams
gal_data_t *fromvector; /* Extract columns from a vector column.*/
uint8_t keepvectfin; /* Keep in.s --tovector & --fromvector. */
gal_list_str_t *tovector; /* Merge columns into a vector column. */
+ uint8_t transpose; /* Transpose vector columns. */
gal_list_str_t *catrowfile; /* Filename to concat column wise. */
gal_list_str_t *catrowhdu; /* HDU/extension for the catcolumn. */
gal_data_t *colmetadata; /* Set column metadata. */
@@ -132,7 +134,7 @@ struct tableparams
int txtf64precision; /* Precision of float32 in text. */
/* Internal. */
- struct column_pack *outcols; /* Output column packages. */
+ struct column_pack *colpack; /* Output column packages. */
gal_data_t *noblank; /* Remove rows that have blank. */
gal_data_t *table; /* Linked list of output table columns. */
struct wcsprm *wcs; /* WCS structure for conversion. */
diff --git a/bin/table/table.c b/bin/table/table.c
index ff1ece15..30011aa1 100644
--- a/bin/table/table.c
+++ b/bin/table/table.c
@@ -430,11 +430,11 @@ static void
table_select_by_value(struct tableparams *p)
{
gal_data_t *rowids;
+ size_t i, *s, ngood=0;
struct list_select *tmp;
uint8_t *u, *uf, *ustart;
- size_t i, *s, ngood=0;
int inplace=GAL_ARITHMETIC_FLAG_INPLACE;
- gal_data_t *mask, *blmask, *addmask=NULL;
+ gal_data_t *mask, *col, *blmask, *addmask=NULL;
/* It may happen that the input table is empty! In such cases, just
return and don't bother with this step. */
@@ -442,13 +442,14 @@ table_select_by_value(struct tableparams *p)
return;
/* Allocate datasets for the necessary numbers and write them in. */
- mask=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, p->table->dsize, NULL, 1,
- p->cp.minmapsize, p->cp.quietmmap, NULL, NULL, NULL);
+ mask=gal_data_alloc(NULL, GAL_TYPE_UINT8, 1, &p->table->dsize[0],
+ NULL, 1, p->cp.minmapsize, p->cp.quietmmap,
+ NULL, NULL, NULL);
/* Go over each selection criteria and remove the necessary elements. */
for(tmp=p->selectcol;tmp!=NULL;tmp=tmp->next)
{
- /* Make sure the input isn't a vector column. */
+ /* Make sure the selection column isn't a vector column. */
if(tmp->col->ndim!=1)
error(EXIT_FAILURE, 0, "row selection by value (for example with "
"'--range', '--inpolygon', '--equal' or '--noblank') is "
@@ -456,6 +457,19 @@ table_select_by_value(struct tableparams *p)
"this feature, please get in touch with us at '%s' to add "
"it", PACKAGE_BUGREPORT);
+ /* Make sure all the to-be-used table columns at this point have the
+ same number of rows as the selection column (can be different when
+ transposing). */
+ for(col=p->table;col!=NULL;col=col->next)
+ if(tmp->col->dsize[0]!=col->dsize[0])
+ error(EXIT_FAILURE, 0, "the number of rows in the column given "
+ "for selection by value (for example '--range' or '--equal') "
+ "is not the same as the number of rows in the table when "
+ "they are applied. This may happen due to operators like "
+ "'--transpose'. In such cases, you probably want row-based "
+ "operators to have precedence over column-based operators. "
+ "If this is your case, please call '--rowfirst'");
+
/* Do the specific type of selection. */
switch(tmp->type)
{
@@ -911,6 +925,42 @@ table_catcolumn(struct tableparams *p)
+static void
+table_transpose(struct tableparams *p)
+{
+ gal_data_t *tmp;
+ size_t refwidth=p->table->dsize[1];
+
+ /* Temporary error. */
+ if(p->colpack)
+ error(EXIT_FAILURE, 0, "'--transpose' is currently not supported "
+ "with Column Arithmetic. Please pipe the transposed table "
+ "into a new 'asttable' command for doing column arithmetic "
+ "on the new columns");
+
+ /* Basic sanity checks and counting of final output columns. */
+ for(tmp=p->table; tmp!=NULL; tmp=tmp->next)
+ {
+ /* Inputs should be vectors. */
+ if(tmp->ndim!=2)
+ error(EXIT_FAILURE, 0, "only vector columns should be present "
+ "in the table when using '--transpose'");
+ if(tmp->dsize[1] != refwidth)
+ error(EXIT_FAILURE, 0, "all vector columns given to '--transpose' "
+ "should have the same length (number of tokens/elements)");
+
+ /* Apply the transposition. */
+ gal_permutation_transpose_2d(tmp);
+
+ /* Remove extra dimensions if necessary. */
+ if(tmp->dsize[1]==1) tmp->ndim=1;
+ }
+}
+
+
+
+
+
static void
table_fromvector(struct tableparams *p)
{
@@ -925,12 +975,17 @@ table_fromvector(struct tableparams *p)
vector=gal_list_data_select_by_id(p->table, tmp->name, NULL);
if(vector==NULL) table_error_no_column("--fromvector", tmp->name);
+ /* If we don't need this vector column any more, remove it from the
+ table. */
+ if(p->keepvectfin==0) gal_list_data_remove(&p->table, vector);
+
/* Make sure the selected column is actually a vector. */
if(vector->ndim!=2)
error(EXIT_FAILURE, 0, "column '%s' (given to '--fromvector') "
"is not a vector", tmp->name);
/* Loop over the values and make sure they are within the range. */
+ indexs=NULL;
iarr=tmp->array;
for(i=0;i<tmp->size;++i)
{
@@ -959,16 +1014,10 @@ table_fromvector(struct tableparams *p)
ext=gal_table_col_vector_extract(vector, indexs);
gal_list_data_last(p->table)->next=ext;
- /* Remove the vector column (if requested). */
- if(p->keepvectfin==0)
- {
- gal_list_data_remove(&p->table, vector);
- gal_data_free(vector);
- }
+ /* Clean up (remove the vector column, if requested). */
+ gal_list_sizet_free(indexs);
+ if(p->keepvectfin==0) gal_data_free(vector);
}
-
- /* Clean up. */
- gal_list_sizet_free(indexs);
}
@@ -987,7 +1036,7 @@ table_tovector(struct tableparams *p)
for(tstr=p->tovector;tstr!=NULL;tstr=tstr->next)
{
/* Extract the separate csv. */
- ids=gal_options_parse_csv_strings_raw(tstr->v, NULL, 0);
+ ids=gal_options_parse_csv_strings_to_data(tstr->v, NULL, 0);
/* Allocate an array of dataset pointers to keep the columns that
should be removed. */
@@ -1493,7 +1542,7 @@ table_txt_formats(struct tableparams *p)
/*************** Top function *******************/
/**************************************************************/
void
-table(struct tableparams *p)
+table_column(struct tableparams *p)
{
/* Concatenate the columns of tables (if required). */
if(p->catcolumnfile) table_catcolumn(p);
@@ -1501,6 +1550,20 @@ table(struct tableparams *p)
/* Extract columns from vector. */
if(p->fromvector) table_fromvector(p);
+ /* Merge columns into a vector column. */
+ if(p->tovector) table_tovector(p);
+
+ /* If any arithmetic operations are needed, do them. */
+ if(p->colpack) arithmetic_operate(p);
+}
+
+
+
+
+
+void
+table_row(struct tableparams *p)
+{
/* Concatenate the rows of multiple tables (if required). */
if(p->catrowfile) table_catrows(p);
@@ -1511,23 +1574,29 @@ table(struct tableparams *p)
if(p->sort) table_sort(p);
/* If the output number of rows is limited, apply them. */
- if( p->rowrange
+ if( p->rowrange
|| p->rowrandom
|| p->head!=GAL_BLANK_SIZE_T
|| p->tail!=GAL_BLANK_SIZE_T )
table_select_by_position(p);
- /* If any arithmetic operations are needed, do them. */
- if(p->outcols)
- arithmetic_operate(p);
+ /* Transpose the input table. */
+ if(p->transpose) table_transpose(p);
+}
+
- /* Merge columns into a vector column. */
- if(p->tovector) table_tovector(p);
- /* When column metadata should be updated. */
- if(p->colmetadata) table_colmetadata(p);
- /* When any columns with blanks should be removed. */
+
+void
+table(struct tableparams *p)
+{
+ /* Do the requested operations. */
+ if(p->rowfirst) { table_row(p); table_column(p); }
+ else { table_column(p); table_row(p); }
+
+ /* Last steps (independent of '--rowfirst'). */
+ if(p->colmetadata) table_colmetadata(p);
if(p->noblankend) table_noblankend(p);
/* Write the output or a warning/error (it can become NULL!) */
diff --git a/bin/table/ui.c b/bin/table/ui.c
index 28b064b2..09c7b07d 100644
--- a/bin/table/ui.c
+++ b/bin/table/ui.c
@@ -66,14 +66,15 @@ static char
args_doc[] = "ASTRdata";
const char
-doc[] = GAL_STRINGS_TOP_HELP_INFO PROGRAM_NAME" can be used to view the "
- "information, select columns, or convert tables. The inputs and outputs "
- "can be plain text (with white-space or comma as delimiters), FITS ascii, "
- "or FITS binary tables. The output columns can either be selected by "
- "number (counting from 1), name or using regular expressions. For regular "
- "expressions, enclose the value to the '--column' ('-c') option in "
- "slashes ('\\', as in '-c\\^mag\\'). To print the selected columns on the "
- "command-line, don't specify an output file.\n"
+doc[] = GAL_STRINGS_TOP_HELP_INFO PROGRAM_NAME" can be used to view "
+ "the information, select columns, or convert tables. The inputs and "
+ "outputs can be plain text (with white-space or comma as delimiters), "
+ "FITS ascii, or FITS binary tables. The output columns can either be "
+ "selected by number (counting from 1), name or using regular "
+ "expressions. For regular expressions, enclose the value to the "
+ "'--column' ('-c') option in slashes ('\\', as in '-c\\^mag\\'). "
+ "To print the selected columns on the command-line, don't specify "
+ "an output file.\n"
GAL_STRINGS_MORE_HELP_INFO
/* After the list of options: */
"\v"
@@ -516,9 +517,9 @@ ui_list_select_free(struct list_select *list, int freevalue)
/**************************************************************/
/*************** Packaged columns *******************/
/**************************************************************/
-/* Return the last outcols element. */
+/* Return the last 'colpack' element. */
static struct column_pack *
-ui_outcols_last(struct column_pack *list)
+ui_colpack_last(struct column_pack *list)
{
if(list)
{
@@ -535,7 +536,7 @@ ui_outcols_last(struct column_pack *list)
/* Allocate a clean 'out_columns' structure and put it at the top of the
list. */
static struct column_pack *
-ui_outcols_add_new_to_end(struct column_pack **list)
+ui_colpack_add_new_to_end(struct column_pack **list)
{
struct column_pack *last, *node;
@@ -556,7 +557,7 @@ ui_outcols_add_new_to_end(struct column_pack **list)
add this node. */
if(*list)
{
- last=ui_outcols_last(*list);
+ last=ui_colpack_last(*list);
last->next=node;
}
else
@@ -570,8 +571,8 @@ ui_outcols_add_new_to_end(struct column_pack **list)
-static void
-ui_outcols_free(struct column_pack *list)
+void
+ui_colpack_free(struct column_pack *list)
{
struct column_pack *tmp;
while(list!=NULL)
@@ -661,118 +662,112 @@ static void
ui_columns_prepare(struct tableparams *p, gal_list_str_t *lines)
{
int tableformat;
- gal_data_t *strs;
- char *c, **strarr;
gal_data_t *colinfo=NULL;
struct column_pack *node, *last;
gal_list_str_t *tmp, *colstoread=NULL;
- size_t i, totcalled=0, numcols, numrows;
+ size_t i, totcalled=0, numcols, numrows, numsimple;
+ char *str, countstr[11]; /* an un-signed 32-bit integer takes 10 chars */
- /* Go over the whole original list (where each node may have more than
- one value separated by a comma. */
+ /* Go over the list of requested columns from the main input. */
for(tmp=p->columns;tmp!=NULL;tmp=tmp->next)
{
- /* Remove any possibly commented new-line where we have a backslash
- followed by a new-line character (replace the two characters with
- two single space characters). This can happen with the 'arith'
- argument in a script, when it gets long (bug #58371). But to be
- general in other cases too, we'll just correct it here. */
- for(c=tmp->v;*c!='\0';++c)
- if(*c=='\\' && *(c+1)=='\n') { *c=' '; *(++c)=' '; }
-
- /* Read the different comma-separated strings into an array (within a
- 'gal_data_t'). */
- strs=gal_options_parse_csv_strings_raw(tmp->v, NULL, 0);
- strarr=strs->array;
-
- /* Go over all the given colum names/numbers. */
- for(i=0;i<strs->size;++i)
+ /* For easy reading. */
+ str=tmp->v;
+
+ /* If this is an arithmetic column. */
+ if(!strncmp(str, ARITHMETIC_CALL, ARITHMETIC_CALL_LENGTH))
+ {
+ /* Arithmetic operations may be done on columns from other files
+ (for example with '--catcolumnfile'). We therefore need to
+ check if the requested column is in the main input file or
+ not. If not, it should be set when column arithmetic
+ starts. To do this, we need to get the input's column
+ information. */
+ if(colinfo==NULL)
+ colinfo=gal_table_info(p->filename, p->cp.hdu, lines,
+ &numcols, &numrows, &tableformat);
+
+ /* If this is the first arithmetic operation and the user has
+ already asked for some columns, we'll need to put all
+ previously requested simply-printed columns into an 'colpack'
+ structure, then add this arithmetic operation's 'colpack'. */
+ if(p->colpack==NULL && colstoread)
+ {
+ /* Allocate an empty structure and set the necessary
+ pointers. */
+ node=ui_colpack_add_new_to_end(&p->colpack);
+ node->start=0;
+ node->numsimple=gal_list_str_number(colstoread);
+ totcalled=node->numsimple;
+ }
+
+ /* Add a new column pack for this arithmetic operation, then read
+ all the tokens (while specifying which columns it needs). */
+ node=ui_colpack_add_new_to_end(&p->colpack);
+ arithmetic_init(p, &node->arith, &colstoread, &totcalled,
+ str+ARITHMETIC_CALL_LENGTH, colinfo, numcols);
+ }
+
+ /* This is a simple column (no change in values). */
+ else
{
- /* See if this is an arithmetic column to be processed, or its
- just a "simple" column (where */
- if(!strncmp(strarr[i], ARITHMETIC_CALL, ARITHMETIC_CALL_LENGTH))
+ /* If the value is '_all', then we should add all the input's
+ columns. Otherwise, just add this string. */
+ if( !strcmp(str, "_all") )
{
- /* Arithmetic operations may be done on columns from other
- files (for example with '--catcolumnfile'). We therefore
- need to check if the requested column is in the main input
- file or not. If not, it should be set when column
- arithmetic starts. To do this, we need to get the input's
- column information. */
+ /* Load column information (it not already loaded). */
if(colinfo==NULL)
colinfo=gal_table_info(p->filename, p->cp.hdu, lines,
- &numcols, &numrows, &tableformat);
-
- /* If this is the first arithmetic operation and the user has
- already asked for some columns, we'll need to put all
- previously requested simply-printed columns into an
- 'outcols' structure, then add this arithmetic operation's
- 'outcols'. */
- if(p->outcols==NULL && colstoread)
+ &numcols, &numrows,
+ &tableformat);
+
+ /* Add all the input column counters to the list of columns
+ to read */
+ numsimple=gal_list_data_number(colinfo);
+ for(i=0;i<numsimple;++i)
{
- /* Allocate an empty structure and set the necessary
- pointers. */
- node=ui_outcols_add_new_to_end(&p->outcols);
- node->start=0;
- node->numsimple=gal_list_str_number(colstoread);
- totcalled=node->numsimple;
+ sprintf(countstr, "%u", (uint32_t)(i+1));
+ gal_list_str_add(&colstoread, countstr, 1);
}
-
- /* Add a new column pack, then read all the tokens (while
- specifying which columns it needs). */
- node=ui_outcols_add_new_to_end(&p->outcols);
- arithmetic_init(p, &node->arith, &colstoread, &totcalled,
- strarr[i]+ARITHMETIC_CALL_LENGTH, colinfo,
- numcols);
- free(strarr[i]);
}
-
- /* This is a simple column (no change in values). */
else
{
- /* Add this column to the list of columns to read. */
- gal_list_str_add(&colstoread, strarr[i], 0);
+ numsimple=1;
+ gal_list_str_add(&colstoread, str, 1);
+ }
- /* See if we have packaged the output columns. */
- if(p->outcols)
+ /* See if we have packaged the output columns. */
+ if(p->colpack)
+ {
+ /* If the previous column package was an arithmetic
+ operation, allocate a new node. */
+ last=ui_colpack_last(p->colpack);
+ if(last->arith)
{
- /* If the previous column package was an arithmetic
- operation, allocate a new node. */
- last=ui_outcols_last(p->outcols);
- if(last->arith)
- {
- node=ui_outcols_add_new_to_end(&p->outcols);
- node->start=totcalled;
- node->numsimple=1;
- }
-
- /* The previous package of columns are simple (we don't
- need to change their value), so we can just increment
- the number of columns there and don't need to allocate
- a new one. */
- else
- last->numsimple+=1;
+ node=ui_colpack_add_new_to_end(&p->colpack);
+ node->start=totcalled;
+ node->numsimple=numsimple;
}
- /* Increment the total number of called columns. */
- totcalled+=1;
+ /* The previous package of columns are simple (we don't need
+ to change their value), so we can just increment the
+ number of columns there and don't need to allocate a new
+ one. */
+ else
+ last->numsimple+=numsimple;
}
- /* The pointer allocated string is either being used (and later
- freed) else, or has already been freed. So its necessary to
- set it to NULL. */
- strarr[i]=NULL;
+ /* Increment the total number of called columns. */
+ totcalled+=1;
}
-
- /* Clean up. */
- gal_data_free(strs);
}
/* For a check
- if(p->outcols)
+ if(p->colpack)
{
struct column_pack *tmp;
struct arithmetic_token *atmp;
- for(tmp=p->outcols;tmp!=NULL;tmp=tmp->next)
+ for(tmp=p->colpack;tmp!=NULL;tmp=tmp->next)
if(tmp->arith)
{
printf("Arithmetic: \n");
@@ -920,8 +915,8 @@ ui_check_select_sort_before(struct tableparams *p,
gal_list_str_t *lines,
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=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;
@@ -929,8 +924,8 @@ ui_check_select_sort_before(struct tableparams *p,
gal_list_str_t *lines,
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=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;
@@ -1107,7 +1102,8 @@ ui_check_select_sort_before(struct tableparams *p,
gal_list_str_t *lines,
for(k=0;k<SELECT_TYPE_NUMBER;++k)
for(dtmp=select[k];dtmp!=NULL;dtmp=dtmp->next)
{
- if(*sortindout!=GAL_BLANK_SIZE_T && selectindout[i]==*sortindout)
+ if( *sortindout!=GAL_BLANK_SIZE_T
+ && selectindout[i]==*sortindout)
{
selecttypeout[i]=k;
selectindout[i]=*sortindout;
@@ -1262,12 +1258,13 @@ ui_preparations(struct tableparams *p)
extra columns. */
if(p->selection || p->sort)
ui_check_select_sort_before(p, lines, &nselect, &origoutncols,
- &sortindout, &selectindout, &selecttypeout);
+ &sortindout, &selectindout,
+ &selecttypeout);
/* If we have any arithmetic operations, we need to make sure how many
columns match every given column name. */
- p->colmatch = ( p->outcols
+ p->colmatch = ( p->colpack
? gal_pointer_allocate(GAL_TYPE_SIZE_T,
gal_list_str_number(p->columns),
1, __func__, "p->colmatch")
@@ -1428,13 +1425,11 @@ ui_free_report(struct tableparams *p)
/* Free the allocated arrays: */
free(p->cp.hdu);
free(p->cp.output);
- ui_outcols_free(p->outcols);
gal_list_data_free(p->table);
if(p->wcshdu) free(p->wcshdu);
gal_list_data_free(p->noblank);
gal_list_str_free(p->columns, 1);
if(p->colmatch) free(p->colmatch);
- if(p->colarray) free(p->colarray);
gal_list_data_free(p->colmetadata);
gal_list_str_free(p->catcolumnhdu, 1);
gal_list_str_free(p->catcolumnfile, 1);
diff --git a/bin/table/ui.h b/bin/table/ui.h
index b2cda224..445b1a07 100644
--- a/bin/table/ui.h
+++ b/bin/table/ui.h
@@ -33,7 +33,8 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
/* Option groups particular to this program. */
enum program_args_groups
{
- UI_GROUP_OUTCOLS = GAL_OPTIONS_GROUP_AFTER_COMMON,
+ UI_GROUP_PRECEDENCE = GAL_OPTIONS_GROUP_AFTER_COMMON,
+ UI_GROUP_OUTCOLS,
UI_GROUP_OUTROWS,
};
@@ -81,8 +82,10 @@ enum option_keys_enum
UI_KEY_ENVSEED,
UI_KEY_ROWRANGE,
UI_KEY_TOVECTOR,
+ UI_KEY_ROWFIRST,
UI_KEY_ROWRANDOM,
UI_KEY_INPOLYGON,
+ UI_KEY_TRANSPOSE,
UI_KEY_OUTPOLYGON,
UI_KEY_FROMVECTOR,
UI_KEY_CATCOLUMNRAWNAME,
@@ -98,6 +101,9 @@ ui_read_check_inputs_setup(int argc, char *argv[], struct
tableparams *p);
void
ui_list_select_free(struct list_select *list, int freevalue);
+void
+ui_colpack_free(struct column_pack *list);
+
void
ui_free_report(struct tableparams *p);
diff --git a/configure.ac b/configure.ac
index 702fd691..60b275ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -286,7 +286,6 @@ AC_MSG_RESULT( $path_warning )
has_gsl=yes
has_libgit2=1
has_cmath=yes
-with_python=no
has_wcslib=yes
has_cfitsio=yes
has_libtiff=yes
@@ -770,7 +769,7 @@ AS_IF([test "x$has_topcat" = "xno"], [anywarnings=yes])
AC_ARG_WITH([python],
[AS_HELP_STRING([--with-python],
[enable support for python])],
- [with_python=yes], [])
+ [], [with_python=no])
AS_IF([test "x$with_python" == xyes],
[
# Variables to simplify commands below.
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 3785e217..fe9d971a 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -272,6 +272,7 @@ Tutorials
* Detecting large extended targets:: NoiseChisel for huge extended targets.
* Building the extended PSF:: How to extract an extended PSF from science
data.
* Sufi simulates a detection:: Simulating a detection.
+* Detecting lines and extracting spectra in 3D data:: Extracting spectra and
emission line properties.
General program usage tutorial
@@ -318,6 +319,16 @@ Building the extended PSF
* Uniting the different PSF components:: Merging all the components into one
PSF.
* Subtracting the PSF:: Having the PSF, we now want to subtract it.
+Detecting lines and extracting spectra in 3D data
+
+* Viewing spectra and redshifted lines:: Interactively see the spectra of an
object
+* Sky lines in optical IFUs:: How to see sky lines in a cube.
+* Continuum subtraction:: Removing the continuum from a data cube.
+* 3D detection with NoiseChisel:: Finding emission-lines and their spectra.
+* 3D measurements and spectra:: Measuring 3d properties including spectra.
+* Extracting a single spectrum and plotting it:: Extracting a single vector
row.
+* Pseudo narrow-band images:: Collapsing the third dimension into a 2D image.
+
Installation
* Dependencies:: Necessary packages for Gnuastro.
@@ -659,7 +670,7 @@ MakeCatalog measurements
* Surface brightness measurements:: Various ways to measure surface
brightness.
* Morphology measurements nonparametric:: Non-parametric morphology.
* Morphology measurements elliptical:: Elliptical morphology measurements.
-* Spectra measurement in a cube:: How to get the value of a label across all
slices.
+* Measurements per slice spectra:: Measurements on each slice (like spectra).
Invoking MakeCatalog
@@ -718,9 +729,9 @@ High-level calculations
CosmicCalculator
-* Distance on a 2D curved space:: Distances in 2D for simplicity
+* Distance on a 2D curved space:: Distances in 2D for simplicity.
* Extending distance concepts to 3D:: Going to 3D (our real universe).
-* Invoking astcosmiccal:: How to run CosmicCalculator
+* Invoking astcosmiccal:: How to run CosmicCalculator.
Invoking CosmicCalculator
@@ -2002,6 +2013,7 @@ For an explanation of the conventions we use in the
example codes through the bo
* Detecting large extended targets:: NoiseChisel for huge extended targets.
* Building the extended PSF:: How to extract an extended PSF from science
data.
* Sufi simulates a detection:: Simulating a detection.
+* Detecting lines and extracting spectra in 3D data:: Extracting spectra and
emission line properties.
@end menu
@@ -2329,7 +2341,7 @@ The returned value is @mymath{9.06711} arcmin@mymath{^2}.
In other words, the image does cover this area, but there is no data in more
than half of the pixels.
So let's calculate the area coverage over-which we actually have data.
-The FITS world coordinate system (WCS) meta data standard contains the key to
answering this question.
+The FITS world coordinate system (WCS) metadata standard contains the key to
answering this question.
Run the following command to see all the FITS keywords (metadata) for one of
the images (almost identical with the other images because they are scaled to
the same region of Sky):
@example
@@ -2346,7 +2358,7 @@ We can thus conclude that the value of @code{CDELT*} is
in units of degrees-per-
In the FITS standard the @code{CDELT} keywords are optional.
When @code{CDELT} keywords are not present, the @code{PC} matrix is assumed to
contain @emph{both} the coordinate rotation and scales.
Note that not all FITS writers use the @code{CDELT} convention.
-So you might not find the @code{CDELT} keywords in the WCS meta data of some
FITS files.
+So you might not find the @code{CDELT} keywords in the WCS metadata of some
FITS files.
However, all Gnuastro programs (which use the default FITS keyword writing
format of WCSLIB) write their output WCS with the @code{CDELT} convention, even
if the input does not have it.
If your dataset does not use the @code{CDELT} convention, you can feed it to
any (simple) Gnuastro program (for example, Arithmetic) and the output will
have the @code{CDELT} keyword.
See Section 8 of the
@url{https://fits.gsfc.nasa.gov/standard40/fits_standard40aa-le.pdf, FITS
standard} for more}.
@@ -7216,7 +7228,7 @@ Each image or dataset will have its own particularities
that you will have to ta
-@node Sufi simulates a detection, , Building the extended PSF, Tutorials
+@node Sufi simulates a detection, Detecting lines and extracting spectra in 3D
data, Building the extended PSF, Tutorials
@section Sufi simulates a detection
@cindex Azophi
@@ -7774,12 +7786,886 @@ It was nearly sunset and they had to begin preparing
for the night's measurement
+@node Detecting lines and extracting spectra in 3D data, , Sufi simulates a
detection, Tutorials
+@section Detecting lines and extracting spectra in 3D data
+
+@cindex IFU
+@cindex MUSE
+@cindex ACIS
+@cindex Pixel
+@cindex Voxel
+@cindex Spectrum
+@cindex 3D data cube
+@cindex Integral field unit
+@cindex Cube (3D) spectrums
+@cindex Hyperspectral imaging
+3D data cubes are an increasingly common format of data products in
observational astronomy.
+As opposed to 2D images (where each 2D ``picture element'' or ``pixel'' covers
an infinitesimal area on the surface of the sky), 3D data cubes contain
``volume elements'' or ``voxels'' that are also connected in a third dimension.
+
+The most common case of 3D data in observational astrophysics is when the
first two dimensions are spatial (RA and Dec on the sky), and the third
dimension is wavelength.
+This type of data is generically (also outside of astronomy) known as
Hyperspectral
imaging@footnote{@url{https://en.wikipedia.org/wiki/Hyperspectral_imaging}}.
+For example high-level data products of Integral Field Units (IFUs) like
MUSE@footnote{@url{https://en.wikipedia.org/wiki/Multi-unit_spectroscopic_explorer}}
in the optical,
ACIS@footnote{@url{https://en.wikipedia.org/wiki/Advanced_CCD_Imaging_Spectrometer}}
in the X-ray, or in the radio where most data are 3D cubes.
+
+@cindex Abell 370 galaxy cluster
+In this tutorial, we'll use a small crop of a reduced deep MUSE cube centered
on the @url{https://en.wikipedia.org/wiki/Abell_370, Abell 360} galaxy cluster
from the Pilot-WINGS survey; see @url{https://arxiv.org/abs/2202.04663,
Lagattuta et al. 2022}.
+Abell 360 has a spiral galaxy in its background that is stretched due to the
cluster's gravitational potential to create a beautiful arch.
+If you haven't seen it yet, have a look at some of its images in the Wikipedia
link above before continuing.
+
+The Pilot-WINGS survey data are available in its
webpage@footnote{@url{https://astro.dur.ac.uk/~hbpn39/pilot-wings.html}}.
+The cube of the @emph{core} region is 10.2GBs.
+This can be prohibitivly large to download (and later process) on many
networks and smaller computers.
+Therefore, in this demonstration we won't be using the full cube.
+We have prepared a small crop@footnote{You can download the full cube and
create the crop your self with the commands below.
+Due to the decompression of the +10GB file that is necessary for the
compressed downloaded file (note that its suffix is @file{.fits.gz}), the Crop
command will take a little long.
+@example
+$ wget https://astro.dur.ac.uk/~hbpn39/pilotWINGS/A370_PilotWINGS_CORE.fits.gz
+$ astcrop A370_PilotWINGS_CORE.fits.gz -hDATA --mode=img \
+ --section=200:300,100:200 -oa370-crop.fits --metaname=DATA
+$ astcrop A370_PilotWINGS_CORE.fits.gz -hSTAT --mode=img --append \
+ --section=200:300,100:200 -oa370-crop.fits --metaname=STAT
+@end example
+} of the full cube that you can download with the first command below.
+The randomly selected crop is centered on (RA,Dec) of (39.96769,-1.58930),
with a width of about 27 arcseconds.
+
+@example
+$ mkdir tutorial-3d
+$ cd tutorial-3d
+$ wget http://akhlaghi.org/data/a370-crop.fits # Downloads 287 MB
+@end example
+
+In the sections below, we will first review how you can visually inspect a 3D
datacube in DS9 and interactively see the spectra of any region.
+We will then subtract the continuum emission, detect the emission-lines within
this cube and extract their spectra.
+We will finish with creating pseudo narrow-band images optimized for some of
the emission lines.
+
+@menu
+* Viewing spectra and redshifted lines:: Interactively see the spectra of an
object
+* Sky lines in optical IFUs:: How to see sky lines in a cube.
+* Continuum subtraction:: Removing the continuum from a data cube.
+* 3D detection with NoiseChisel:: Finding emission-lines and their spectra.
+* 3D measurements and spectra:: Measuring 3d properties including spectra.
+* Extracting a single spectrum and plotting it:: Extracting a single vector
row.
+* Pseudo narrow-band images:: Collapsing the third dimension into a 2D image.
+@end menu
+
+@node Viewing spectra and redshifted lines, Sky lines in optical IFUs,
Detecting lines and extracting spectra in 3D data, Detecting lines and
extracting spectra in 3D data
+@subsection Viewing spectra and redshifted lines
+
+In @ref{Detecting lines and extracting spectra in 3D data} we downloaded a
small crop from the Pilot-WINGS survey of Abell 370 cluster; observed with MUSE.
+In this section, we will review how you can visualize/inspect a datacube using
that example.
+With the first command below, we'll open DS9 such that each 2D slice of the
cube (at a fixed wavelength) is seen as a single image.
+If you move the slider in the ``Cube'' window (that also opens), you can view
the same field at different wavelengths.
+We are ending the first command with a `@code{&}' so you can continue viewing
DS9 while using the command-line (press one extra @code{ENTER} to see the
prompt).
+With the second command, you can see that the spacing between each slice is
@mymath{1.25\times10^{-10}} meters (or 1.25 Angstroms).
+
+@example
+$ astscript-fits-view a370-crop.fits -h1 --ds9scale="limits -5 20" &
+
+$ astfits a370-crop.fits --pixelscale
+Basic information for --pixelscale (remove info with '--quiet' or '-q')
+ Input: a370-crop.fits (hdu 1) has 3 dimensions.
+ Pixel scale in each FITS dimension:
+ 1: 5.55556e-05 (deg/pixel) = 0.2 (arcsec/pixel)
+ 2: 5.55556e-05 (deg/pixel) = 0.2 (arcsec/pixel)
+ 3: 1.25e-10 (m/slice)
+ Pixel area (on each 2D slice) :
+ 3.08642e-09 (deg^2) = 0.04 (arcsec^2)
+ Voxel volume:
+ 3.85802e-19 (deg^2*m) = 5e-12 (arcsec^2*m) = 0.05 (arcsec^2*A)
+@end example
+
+In the DS9 ``Cube'' window, you will see two numbers on the two sides of the
scroller.
+The left number is the wavelength in meters (WCS coordinate in 3rd dimension)
and the right number is the slice number (slice number or array coordinates in
3rd dimension).
+You can manually edit any of these numbers and press ENTER to go to that slice
in any coordinate system.
+If you want to go one-by-one, simply press the ``Next'' button.
+The first few slides are very noisy, but in the rest the noise level decreases
and the galaxies are more obvious.
+
+As you slide between the different wavelengths, you see that the noise-level
is not constant and in some slices, the sky noise is very strong (for example,
go to slice 3201 and press the ``Next'' button).
+We will discuss these issues below (in @ref{Sky lines in optical IFUs}).
+To view the spectra of a region in DS9 take the following steps:
+
+@enumerate
+@item
+Click somewhere on the image (to make sure DS9 receives your keyboard inputs),
then press @code{Ctrl+R} to activate regions and click on the brighest galaxy
of this cube (center-right, at RA, Dec of 39.9659175 and -1.5893075).
+@item
+A thin green circle will show up; this is called a ``region'' in DS9.
+@item
+Double-click on the region, and you will see a ``Circle'' window.
+@item
+Within the ``Circle'' window, click on the ``Analysis'' menu and select ``Plot
3D''.
+@item
+A second ``Circle'' window will open that shows the spectra within your
selected region.
+This is just the sum of values on each slice within the region.
+@item
+Don't close the second ``circle'' window (that shows the spectrum).
+Click and hold the region in DS9, and move it to other objects within the cube.
+You will see that the spectrum changes as you move the region, and you can see
that different objects have very different spectra.
+You can even see the spectra of only one part of a galaxy, not the whole
galaxy.
+@item
+Take the region back to the first (brightest) galaxy that we originally
started with.
+@item
+Slide over different wavelengths in the ``Cube'' window, you will see the
light-blue line moving through the spectrum as you slide to different
wavelengths.
+This line shows the wavelength of the displayed image in the main window over
the spectra.
+@cindex H-alpha
+@item
+The strongest emission line in this galaxy appears to be around 8500 Angstroms
or @mymath{8.5\times10^{-7}} meters.
+From the position of the @url{https://en.wikipedia.org/wiki/Balmer_jump,
Balmer break} (blue-ward of 5000 Angstroms for this galaxy), the strong seems
to be H-alpha.
+@item
+To confirm that this is H-alpha, you can select the ``Edit'' menu in the
spectrum window and select ``Zoom''.
+@item
+Double-click and hold (for next step also) somewhere before the strongest line
and slightly above the continuum (for example at @code{8E-07} in the horizontal
and @mymath{60\times10^{-20}}erg/Angstrom/cm@mymath{^2}/s on the vertical).
+As you move your cursor (while holding), you will see a rectangular box
getting created.
+@item
+Move the bottom-left corner of the box to somewhere after the strongest line
and below the continuum.
+For example at @code{9E-07} and
@mymath{20\times10^{-20}}erg/Angstrom/cm@mymath{^2}/s.
+@item
+Once you remove your finger from the mouse/touchpad, it will zoom-in to that
part of the spectrum.
+@item
+To zoom out to the full spectrum, just press the right mouse button over the
spectra (or tap with two fingers on a touchpad).
+@item
+Select that zoom-box again to see the brightest line much more clearly.
+You can also see the two lines of the Nitrogen II doublet that sandwitch
H-alpha.
+Beside its relative position to the Balmer break, this is further evidence
that the strongest line is H-alpha.
+@item
+@cindex NII doublet
+Let's have a look at the galaxy in its best glory: right over the H-alpha line:
+Move the wavelength slider accurately (by pressing the ``Previous'' or
``Next'' buttons) such that the blue line falls in the middle of the H-alpha
line.
+We see that the wavelength at this slice is @code{8.56593e-07} meters or
8565.93 Angstroms.
+Please compare the image of the galaxy at this wavelength with the wavelenghts
before (by pressing ``Next'' or ``Previous'').
+You will also see that it is much more extended and brighter than other
wavelengths!
+H-alpha shows the un-obscured star formation of the galaxy!
+@end enumerate
+
+@cartouche
+@noindent
+@strong{Automaticly going to next slice:} When you want to get a general
feeling of the cube, pressing the ``Next'' button many times is annoying and
slow.
+To automatically shift between the slices, you can press the ``Play'' button
in the DS9 ``Cube'' window.
+You can adjust the time it stays on each slice by clicking on the ``Interval''
menu and selecting lower values.
+@end cartouche
+
+Knowing that this is H-alpha at 8565.93 Angstroms, you can get the redshift of
the galaxy with the first command below and the location of all other expected
lines in Gnuastro's spectral line database with the second command.
+Because there are many lines in the second command (more than 200!), with the
third command, we'll only limit it to the Balmer series (that start with
@code{H-}) using @command{grep}.
+The output of the second command prints the metadata on the top (that is not
shown any more in the third command due to the @code{grep} call).
+To be complete, the first column is the observed wavelength of the given line
in the given redshift and the second column is the name of the line.
+
+@example
+# Redshift where H-alpha falls on 8565.93.
+$ astcosmiccal --obsline=H-alpha,8565.93 --usedredshift
+0.305221
+
+# Wavelength of all lines in Gnuastro's database at this redshift
+$ astcosmiccal --obsline=H-alpha,8565.93 --listlinesatz
+
+# Only the Balmer series (Lines starting with 'H-'; given to Grep).
+$ astcosmiccal --obsline=H-alpha,8565.93 --listlinesatz | grep H-
+4812.13 H-19
+4818.29 H-18
+4825.61 H-17
+4834.36 H-16
+4844.95 H-15
+4857.96 H-14
+4874.18 H-13
+4894.79 H-12
+4921.52 H-11
+4957.1 H-10
+5006.03 H-9
+5076.09 H-8
+5181.83 H-epsilon
+5353.68 H-delta
+5665.27 H-gamma
+6345.11 H-beta
+8565.93 H-alpha
+4758.84 H-limit
+@end example
+
+@cindex H-beta
+Zoom-out to the full spectrum and move the displayed slice to the location of
the first emission line that is blue-ward (at shorter wavelengths) of H-alpha
(at around 6300 Angstroms) and follow the previous steps to confirm that you
are on its center.
+You will see that it falls exactly on @mymath{6.34468\times10^{-7}} m or
6344.68 Angstroms.
+Now, have a look at the balmer lines above.
+You have found the H-beta line!
+
+The rest of the @url{https://en.wikipedia.org/wiki/Balmer_series, Balmer
series} that you see in the list above (like H-gamma, H-delta and H-epsilon)
are visible only as absorption lines.
+Please check their location by moving the blue line on the wavelengths above
and confirm the spectral absorption lines with the ones above.
+The Balmer break is caused by the fact that these stronger Balmer absorption
lines become too close to each other.
+
+Looking back at the full spectrum, you can also confirm that the only other
relatively strong emission line in this galaxy, that is on the blue side of the
spectrum is the weakest OII line that is approximately located at 4864
Angstroms in the observed spectra of this galaxy.
+The numbers after the various OII emission lines show their rest-frame
wavelengths (``OII'' can correspond to many electron transitions, so we should
be clear about which one we are talking about).
+
+@example
+$ astcosmiccal --obsline=H-alpha,8565.93 --listlinesatz | grep O-II-
+4863.3 O-II-3726
+4866.93 O-II-3728
+5634.82 O-II-4317
+5762.42 O-II-4414
+9554.21 O-II-7319
+9568.22 O-II-7330
+@end example
+
+Please stop here and spend some time on doing the exercise above on other
galaxies in the this cube to get a feeling of types of galaxy spectral features
(and later on the full/large cube).
+You will notice that only star-forming galaxies have such strong emission
lines!
+If you enjoy it, go get the full non-cropped cube and investigate the spectra,
redshifts and emission/absorption lines of many more galaxies.
+
+But going into those higher-level details of the physical meaning of the
spectra (as intriguing as they are!) is beyond the scope of this tutorial.
+So we have to stop at this stage unfortuantely.
+Now that you have a relatively good feeling of this small cube, let's start
doing some analysis to extract the spectra of the objects in this cube.
+
+@node Sky lines in optical IFUs, Continuum subtraction, Viewing spectra and
redshifted lines, Detecting lines and extracting spectra in 3D data
+@subsection Sky lines in optical IFUs
+
+@cindex Sky emission-lines
+@cindex O-H lines (from atmosphere)
+As we were visually inspecting the cube in @ref{Viewing spectra and redshifted
lines}, we noticed some slices with very bad noise.
+They will later affect our detection within the cube, so in this section let's
have a fast look at them here.
+We'll start by looking at the two cubes within the downloaded FITS file:
+
+@example
+$ astscript-fits-view a370-crop.fits
+@end example
+
+The cube on the left is the same cube we studied before.
+The cube on the right (which is called @code{STAT}) shows the variance of each
voxel.
+Go to slice 3195 and press ``Next'' to view the subsequent slices.
+Initially (for the first 5 or 6 slices), the noise looks reasonable.
+But as you pass slice 3206, you will see that the noise becomes very bad in
both cubes.
+It stays like this until about slice 3238!
+As you go through the whole cube, you will notice that these slices are much
more frequent in the reddest wavelengths.
+
+@cindex Sky
+@cindex Atmosphere emission lines
+These slices are affected by the emission lines from our own atmosphere!
+The atmosphere's emission in these wavelengths significantly raises the
background level in these slices.
+As a result, the poisson noise also increases significantly (see @ref{Photon
counting noise}).
+During the data reduction, the excess background flux of each slice is removed
as the Sky (or the mean of undetected pixels, see @ref{Sky value}).
+However, the increased Poisson noise (scatter of pixel values) remains!
+
+To see spectrum of the sky emission lines, simply put a region somewhere in
the @code{STAT} cube and generate its spectrum (as we did in @ref{Viewing
spectra and redshifted lines}).
+You will clearly see the comb-like shape of atmospheric emission lines and can
use this to know where to expect them.
+
+
+@node Continuum subtraction, 3D detection with NoiseChisel, Sky lines in
optical IFUs, Detecting lines and extracting spectra in 3D data
+@subsection Continuum subtraction
+@cindex Continuum subtraction
+In @ref{Viewing spectra and redshifted lines}, we visually inspected some of
the most prominent emission lines of the brightest galaxy of the demo MUSE cube
(see @ref{Detecting lines and extracting spectra in 3D data}).
+Here, we will remove the ``continuum'' flux from under the emission lines to
see them more distinctly.
+
+Within a spectra, the continuum is the local ``background'' flux in the
third/wavelength dimension.
+In other words, it is the flux that would be present at that wavelength if the
emission line didn't exist.
+Therefore, to accurately measure the flux of the emission line, we first need
to subtract the continuum.
+One crude way of estimating the continuum flux at every slice is to use the
sigma-clipped median value of that same pixel in the @mymath{\pm{N/2}} slides
around it (for more on sigma-clipping, see @ref{Sigma clipping}).
+
+In this case, @mymath{N=100} should be a good first approximate (since it is
much larger than any of the absorption or emission lines).
+With the first command below, let's use Arithmetic's filtering operators for
estimating the sigma-clipped median only along the third dimension for every
pixel in every slice (see @ref{Filtering operators}).
+With the second command, have a look at the filtered cube and spectra.
+Note that the first command is computationally expensive and may take a minute
or so.
+
+@example
+$ astarithmetic a370-crop.fits set-i --output=filtered.fits \
+ 3 0.2 1 1 100 i filter-sigclip-median
+
+$ astscript-fits-view filtered.fits -h1 --ds9scale="limits -5 20"
+@end example
+
+Looking at the filtered cube above, and sliding through the different
wavelenths, you will see the noise in each slice has been significantly reduced!
+This is expected because each pixel's value is now calculated from 100 others
(along the third dimension)!
+Using the same steps as @ref{Viewing spectra and redshifted lines}, plot the
spectra of the brightest galaxy.
+Then, have a look at its spectra.
+You see that the emission lines have been significantly smoothed out to become
almost@footnote{For more on why Sigma-clipping is only a crude solution to
background removal, see @url{https://arxiv.org/abs/1505.01664, Akhlaghi and
Ichikawa 2015}.} invisible.
+
+You can now subtract this ``continuum'' cube from the input cube to create the
emission-line cube.
+Infact, as you see below, we can do it in a single Arithmetic command
(blending the filtering and subtraction in one command).
+Note how the only difference with the previous Arithmetic command is that we
added an @code{i} before the @code{3} and a @code{-} after
@code{filter-sigclip-median}.
+For more on Arithmetic's powerful notation, see @ref{Reverse polish notation}.
+With the second command below, let's view the input @emph{and}
continuum-subtracted cubes together:
+
+@example
+$ astarithmetic a370-crop.fits set-i --output=no-continuum.fits \
+ i 3 0.2 1 1 100 i filter-sigclip-median -
+
+$ astscript-fits-view a370-crop.fits no-continuum.fits -h1 \
+ --ds9scale="limits -5 20"
+@end example
+
+Once the cubes are open, slide through the different wavelengths.
+Comparing the left (input) and right (continuum-subtracted) slices, you will
rarely see any galaxy in the continuum-subtracted one!
+As its name suggests, the continuum flux is continuously present in all the
wavelengths (with gradual change)!
+But the continuum has been subtracted now; so in the right-side image, you
don't see anything on wavelengths that don't contain a spectral emission line.
+Some dark regions also appear; these are absorption lines!
+Please spend a few minutes sliding through the wavelenghts and seeing how the
emission lines pop-up and disappear again.
+It is almost like skuba diving, with fish appearing out of nowhere and passing
by you.
+
+@cindex Doppler effect
+@cindex Galaxy kinematics
+@cindex Kinematics (galaxies)
+Let's go to slice 3046 (corresponding to 8555.93 Angstroms; just before the
H-alpha line for the brightest galaxy in @ref{Viewing spectra and redshifted
lines}).
+Now press the ``Next'' button to change slices one by one until there is no
more emission in the brightest galaxy.
+As you go to redder slices, you will see that not only does the brightness
increase, but the position of the emission also changes.
+This is the @url{https://en.wikipedia.org/wiki/Doppler_effect, doppler effect}
caused by the rotation of the galaxy: the side that rotating towards us gets
blue-shifted to bluer slices and the one that is going away from us gets
redshifted to redder slices.
+If you go to the emission lines of the other galaxies, you will see that they
move with a different angle!
+We can use this to derive the galaxy's rotational properties and kinematics
(Gnuastro doesn't have this feature yet).
+
+To see the Doppler shift in the spectrum, plot the spectrum over the top-side
of the galaxy (which is visible in slice 3047).
+Then Zoom-in to the H-alpha line (as we did in @ref{Viewing spectra and
redshifted lines}) and press ``Next'' until you reach the end of the H-alpha
emission-line.
+You see that by the time H-alpha disappears in the spectrum, within the cube,
the emission shifts in the vertical axis by about 15 pixels!
+Then, move the region across the same path that the emission passed.
+You will clearly see that the H-alpha and Nitrogen II lines also move with
you, in the zoomed-in spectra.
+Again, try this for several other emission lines, and several other galaxies
to get a good feeling of this important concept when using hyper-spectral 3D
data.
+
+@node 3D detection with NoiseChisel, 3D measurements and spectra, Continuum
subtraction, Detecting lines and extracting spectra in 3D data
+@subsection 3D detection with NoiseChisel
+
+In @ref{Continuum subtraction} we subtracted the continuum emission, leaving
us with only noise and the absorption and emission lines.
+The absorption lines are negative and will be missed by detection methods that
look for a positive skewness@footnote{But if you want to detect the absorption
lines, just multiply the cube by @mymath{-1} and repeat the same steps here
(the noise is symmetic around 0).} (like @ref{NoiseChisel}).
+So we will focus on the detection and extaction of emission lines here.
+
+The first step is to extract the voxels that contain emission signal.
+To do that, we will be using @ref{NoiseChisel}.
+NoiseChisel and @ref{Segment} operate on 2D images or 3D cubes.
+But by default, they are configured for 2D images (some parameters like tile
size take a different number of values based on the dimensionality).
+Therefore, to do 3D detection, the first necessary step is to run NoiseChisel
with the default 3D configuration file.
+
+To see where Gnuastro's programs are installed, you can run the following
command (the printed output is the default location when you install Gnuastro
from source, but if you used another installation method or manually set a
different location, you will see a different output, just use that):
+
+@example
+$ which astnoisechisel
+/usr/local/bin/astnoisechisel
+@end example
+
+As you see, the compiled binary programs (like NoiseChisel) are installed in
the @file{bin/} sub-directory of the install path (@file{/usr/local} in the
example above, may be different on your system).
+The configuration files are in the @file{etc/} sub-directory of the install
path (here only showing NoiseChisel's configuration files):
+
+@example
+$ ls /usr/local/etc/astnoisechisel*.conf
+/usr/local/etc/astnoisechisel-3d.conf
+/usr/local/etc/astnoisechisel.conf
+@end example
+
+@noindent
+We should therefore call NoiseChisel with the 3D configuraiton file like below
(please change @file{/usr/local} to any directory that you find from the
@code{which} command above):
+
+@example
+$ astnoisechisel --config=/usr/local/etc/astnoisechisel-3d.conf \
+ no-continuum.fits --output=det.fits
+@end example
+
+But having to add this long @option{--config} option is annoying and makes the
command hard to read!
+To simplify the calling of NoiseChisel in 3D, let's first make a shell alias
called @command{astnoisechisel-3d} using the @command{alias} command.
+Afterwards, we can just use the alias.
+Afterwards (in the second command below), we are calling the alias, producing
the same output as above.
+Finally (with the last command), let's have a look at NoiseChisel's output:
+
+@example
+$ alias astnoisechisel-3d="astnoisechisel \
+ --config=/usr/local/etc/astnoisechisel-3d.conf"
+
+$ astnoisechisel-3d no-continuum.fits --output=det.fits
+
+$ astscript-fits-view det.fits
+@end example
+
+Similar to its 2D outputs, NoiseChisel's output contains four extensions/HDUs
(see @ref{NoiseChisel output}).
+For a multi-extension file with 3D data, @code{astscript-fits-view} shows each
cube as a separate DS9 ``Frame''.
+In this way, as you slide through the wavelengths, you see the same slice in
all the cubes.
+The third and fourth extensions are the Sky and Sky standard deviation, which
are not relevant here, so you can close them.
+To do that, press on the ``Frame'' button (in the top row of buttons), then
press ``delete'' two times in the second row of buttons.
+
+As a final preparation, manaully set the scale of @code{INPUT-NO-SKY} cube to
a fixed range so the changing flux/noise in each slice doesn't interfer with
visually comparing the data in the slices as you move around:
+@enumerate
+@item
+Click on the @code{INPUT-NO-SKY} cube, so it is selected.
+@item
+Click on the ``Scale'' menu, then the ``Scale Parameters''.
+@item
+For the ``Low'' value set -2 and for the ``High'' value set 5.
+@item
+In the ``Cube'' window, slide between the slices to confirm that the noise
level is visually fixed.
+@item
+Go back to the first slice for the next steps.
+Note that the first and last couple of slices have much higher noise, don't
worry about those.
+@end enumerate
+
+As you press the ``Next'' button in the first few slides, you will notice that
the @code{DETECTION} cube is fully black: showing that nothing has been
detected.
+The first detection pops up in the 55th slice for the galaxy on the top of
this cube.
+As you press ``Next'' you will see that the detection fades away and other
detections pop up.
+Spend a few minutes shifting between the different slices and comparing the
detected voxels with the emission lines in the continuum-subtracted cube (the
@code{INPUT-NO-SKY} extension).
+
+Go ahead to slice 2815 and press ``Next'' a few times.
+You will notice that the detections suddenly start covering the whole slice
and until slice 2859 where the detection map becomes normal (no extra
detections!).
+This is the effect of the sky lines we mentioned before in @ref{Sky lines in
optical IFUs}.
+The increased noise makes the reduction very hard and as a result, a lot of
artifacts appear.
+To reduce the effect of sky lines, we can divide the cube by its standard
deviation (the square root of the variance or @code{STAT} extension; see
@ref{Sky lines in optical IFUs}) and run NoiseChisel afterwards.
+
+@example
+$ astarithmetic no-continuum.fits -h1 a370-crop.fits -hSTAT sqrt / \
+ --output=sn.fits
+
+$ astnoisechisel-3d sn.fits --output=det.fits
+
+$ astscript-fits-view det.fits
+@end example
+
+After the new detection map opens have another look at the specific slices
mentioned above (from slice 2851 to 2859).
+You will see that there are no more detection maps that cover the whole field
of view.
+Scroll the slide counter across the whole cube, you will rarely see such
effects by Sky lines any more.
+But this is just a crude solution and doesn't remove all sky line artifacts.
+For example go to slide 650 and press ``Next''.
+You will see that the artifacts caused by this sky line are so strong that the
solution above wasn't successful.
+For these very strong emission lines, we need to improve the reduction.
+But generally, since the number of sky-line affected slices has significantly
decreased, we can go ahead.
+
+@node 3D measurements and spectra, Extracting a single spectrum and plotting
it, 3D detection with NoiseChisel, Detecting lines and extracting spectra in 3D
data
+@subsection 3D measurements and spectra
+
+In the context of optical IFUs or radio IFUs in astronomy, a ``Spectum'' is
defined as separate measurements on each 2D slice of the 3D cube.
+Each 2D slice is defined by the first two FITS dimensions: the first FITS
dimension is the horizontal axis and the second is the vertical axis.
+As with the tutorial on 2D image analysis (in @ref{Segmentation and making a
catalog}), let's run Segment to see how it works in 3D.
+Like NoiseChisel above, to simplify the commands, let's make an alias (@ref{3D
detection with NoiseChisel}):
+
+@example
+$ alias astsegment-3d="astsegment \
+ --config=/usr/local/etc/astsegment-3d.conf"
+
+$ astsegment-3d det.fits --output=seg.fits
+
+$ astscript-fits-view seg.fits
+@end example
+
+You see that we now have 3D clumps and 3D objects.
+So we can go ahead to do measurements.
+MakeCatalog can do single-valued measurements (as in 2D) on 3D datasets also.
+For example, with the command below, let's get the flux-weighted center (in
the three dimensions) and sum of pixel values.
+There isn't usually a standard name for the third WCS dimension (unlike
Ra/Dec).
+So in Gnuastro, we just call it @option{--w3}.
+With the second command, we are having a look at the first 5 rows.
+Note that we are not using @option{-Y} with @command{asttable} anymore because
it the wavelength column would only be shown as zero (since it is in meters!).
+
+@example
+$ astmkcatalog seg.fits --ids --ra --dec --w3 --sum --output=cat.fits
+
+$ asttable cat.fits -h1 -O --txtf64p=5 --head=5
+# Column 1: OBJ_ID [counter ,i32,] Object identifier.
+# Column 2: RA [deg ,f64,] Flux weighted center (WCS axis 1).
+# Column 3: DEC [deg ,f64,] Flux weighted center (WCS axis 2).
+# Column 4: AWAV [m ,f64,] Flux weighted center (WCS axis 3).
+# Column 5: SUM [input-units,f32,] Sum of sky subtracted values.
+1 3.99677e+01 -1.58660e+00 4.82994e-07 7.311189e+02
+2 3.99660e+01 -1.58927e+00 4.86411e-07 7.872681e+03
+3 3.99682e+01 -1.59141e+00 4.90609e-07 1.314548e+03
+4 3.99677e+01 -1.58666e+00 4.90816e-07 7.798024e+02
+5 3.99659e+01 -1.58930e+00 4.93657e-07 3.255210e+03
+@end example
+
+Besides the single-valued measurements above (that are shared with 2D inputs),
on 3D cubes, MakeCatalog can also do per-slice measurements.
+The options for these measurements are formatted as @option{--*in-slice}.
+With the command below, you can check their list:
+
+@example
+$ astmkcatalog --help | grep in-slice
+ --area-in-slice [3D input] Number of labeled in each slice.
+ --area-other-in-slice [3D input] Area of other lab. in proj area.
+ --area-proj-in-slice [3D input] Num. voxels in '--sumprojinslice'.
+ --sum-err-in-slice [3D input] Error in '--suminslice'.
+ --sum-in-slice [3D input] Sum of values in each slice.
+ --sum-other-err-in-slice [3D input] Area in '--sumotherinslice'.
+ --sum-other-in-slice [3D input] Sum of other lab. in proj area.
+ --sum-proj-err-in-slice [3D input] Error of '--sumprojinslice'.
+ --sum-proj-in-slice [3D input] Sum of proj. area in each slice.
+@end example
+
+For every label and measurement, these options will give many values in a
vector column (see @ref{Vector columns}).
+Let's have a look by asking for the sum of values and area of each label in
each slice associated to each label with the command below.
+There is just one important point: in @ref{3D detection with NoiseChisel}, we
ran NoiseChisel on the signal-to-noise image, not the continuum-subtracted
image!
+So the values to use for the measurement of each label should come from the
@file{no-continuum.fits} file (not @file{seg.fits}).
+
+@example
+$ astmkcatalog seg.fits --ids --ra --dec --w3 --sum \
+ --area-in-slice --sum-in-slice --output=cat.fits \
+ --valuesfile=no-continuum.fits
+
+$ asttable -i cat.fits
+--------
+seg_cat.fits (hdu: 1)
+------- ----- ---- -------
+No.Name Units Type Comment
+------- ----- ---- -------
+1 OBJ_ID counter int32 Object identifier.
+2 RA deg float64 Flux wht center (WCS 1).
+3 DEC deg float64 Flux wht center (WCS 2).
+4 AWAV m float64 Flux wht center (WCS 3).
+5 SUM input-units float32 Sum of sky-subed values.
+6 AREA-IN-SLICE counter int32(3681) Number of pix. in each slice.
+7 SUM-IN-SLICE input-units float32(3681) Sum of values in each slice.
+--------
+Number of rows: 211
+--------
+@end example
+
+You can see that the new @code{AREA-IN-SLICE} and @code{SUM-IN-SLICE} columns
have a @code{(3681)} in their types.
+This shows that unlike the single-valued columns before them, in these
columns, each row has 3681 values (a ``vector'' column).
+If you are not already familiar with vector columns, please take a few minutes
to read @ref{Vector columns}.
+Since a MUSE data cube has 3681 slices, this is effectively the spectrum of
each object.
+
+Let's find the object that corresponds to the H-alpha emission of the
brightest galaxy (that we found in @ref{Viewing spectra and redshifted lines}).
+That emission line was around 8565.93 Angstroms, so let's look for the objects
within @mymath{\pm5} Angstroms of that value (between 8560 to 8570 Angstroms):
+
+@example
+$ asttable cat.fits --range=AWAV,8.560e-7,8.570e-7 -cobj_id,ra,dec -Y
+198 39.965897 -1.589279
+@end example
+
+From the command above, we see that at this wavelength, there was only one
object.
+Let's extract its spectrum by asking for the @code{sum-in-slice} column:
+
+@example
+$ asttable cat.fits --range=AWAV,8.560e-7,8.570e-7 \
+ -carea-in-slice,sum-in-slice
+@end example
+
+If you look into the outputs, you will see that it is a single line!
+It contains a long list of 0 values at the start and @code{nan} values in the
end.
+If you scroll slowly, in the middle of each you will see some non-zero and
non-NaN numbers.
+To help interpret this more easily, let's transpose these vector columns (so
each value of the vector column becomes a row in the output).
+We will use the @option{--transpose} option of Table for this (just note that
since transposition changes the number of rows, it can only be used when your
table only has vector columns and they all have the same number of elements (as
in this case, for more):
+
+@example
+$ asttable cat.fits --range=AWAV,8.560e-7,8.570e-7 \
+ -carea-in-slice,sum-in-slice --transpose
+@end example
+
+We now see the measurements on each slice printed in a separate line (making
it much more easier to visually read).
+However, without a counter, it is very hard to interpret them.
+Let's pipe the output to a new Table command and use column arithmetic's
@code{counter} operator for displaying the slice number (see @ref{Size and
position operators}).
+Note that since we are piping the output, we also added @option{-O} so the
column metadata are also passed to the new instance of Table:
+
+@example
+$ asttable cat.fits --range=AWAV,8.560e-7,8.570e-7 -O \
+ -carea-in-slice,sum-in-slice --transpose \
+ | asttable -c'arith $1 counter swap',2
+...[[truncated]]...
+3040 0 nan
+3041 0 nan
+3042 0 nan
+3043 0 nan
+3044 1 4.311140e-01
+3045 18 3.936019e+00
+3046 161 -5.800080e+00
+3047 360 2.967184e+02
+3048 625 1.912855e+03
+3049 823 5.140487e+03
+3050 945 7.174101e+03
+3051 999 6.967604e+03
+3052 1046 6.468591e+03
+3053 1025 6.457354e+03
+3054 996 6.599119e+03
+3055 966 6.762280e+03
+3056 873 5.014052e+03
+3057 649 2.003334e+03
+3058 335 3.167579e+02
+3059 131 1.670975e+01
+3060 25 -2.953789e+00
+3061 0 nan
+3062 0 nan
+3063 0 nan
+3064 0 nan
+...[[truncated]]...
+
+$ astscript-fits-view seg.fits
+@end example
+
+After DS9 opens with the last command above, go to slice 3044 (which is the
first non-NaN slice in the spectrum above).
+In the @code{OBJECTS} extension of this slice, you see several non-zero pixels.
+The few non-zero pixels on the bottom have a label of 197 and the single
non-zero pixel at a higher Y axis position has a label of 198 (which as we saw
above, was the label of the H-alpha emission of this galaxy).
+The few 197 labeled pixels in this slice are the last voxels of the NII
emission that is just blue-ward of H-alpha.
+
+The single pixel you see in slice 3044 is why you see a value of 1 in the
@code{AREA-IN-SLICE} column.
+As you go to the next slices, if you count the pixels, you will see they add
up to the same number you see in that column.
+The values in the @code{SUM-IN-SLICE} are the sum of values in the
continuum-subtracted cube for those same voxels.
+You should now be able to understand why the @option{--sum-in-slice} column
has NaN values in all other slices: because this label doesn't exist in any
other slice!
+Also, within slices that contain label 198, this column only uses the voxels
that have the label.
+So as you see in the second column above, the area that is used in each
changes.
+
+Therefore @option{--sum-in-slice} or @option{area-in-slice} are the raw 3D
spectrum of each 3D emission-line.
+This is a different concept from the traditional ``spectrum'' where the same
area is used over all the slices.
+To get that you should use the @option{--sumprojinslice} column of MakeCatalog.
+All the @option{--*in-slice} options that contain a @code{proj} in their name
are measurements over the fixed ``projection'' of the 3D volume on the 2D
surface of each slice.
+To see the effect, let's also ask MakeCatalog to measure this projected sum
column:
+
+@example
+$ astmkcatalog seg.fits --ids --ra --dec --w3 --sum \
+ --area-in-slice --sum-in-slice --sum-proj-in-slice \
+ --output=cat.fits --valuesfile=no-continuum.fits
+$ asttable cat.fits --range=AWAV,8.560e-7,8.570e-7 -O \
+ -carea-in-slice,sum-in-slice,sum-proj-in-slice \
+ --transpose \
+ | asttable -c'arith $1 counter swap',2,3
+...[[truncated]]...
+3040 0 nan 8.686357e+02
+3041 0 nan 4.384907e+02
+3042 0 nan 4.994813e+00
+3043 0 nan -1.595918e+02
+3044 1 4.311140e-01 -2.793141e+02
+3045 18 3.936019e+00 -3.251023e+02
+3046 161 -5.800080e+00 -2.709914e+02
+3047 360 2.967184e+02 1.049625e+02
+3048 625 1.912855e+03 1.841315e+03
+3049 823 5.140487e+03 5.108451e+03
+3050 945 7.174101e+03 7.149740e+03
+3051 999 6.967604e+03 6.913166e+03
+3052 1046 6.468591e+03 6.442184e+03
+3053 1025 6.457354e+03 6.393185e+03
+3054 996 6.599119e+03 6.572642e+03
+3055 966 6.762280e+03 6.716916e+03
+3056 873 5.014052e+03 4.974084e+03
+3057 649 2.003334e+03 1.870787e+03
+3058 335 3.167579e+02 1.057906e+02
+3059 131 1.670975e+01 -2.415764e+02
+3060 25 -2.953789e+00 -3.534623e+02
+3061 0 nan -3.745465e+02
+3062 0 nan -2.532008e+02
+3063 0 nan -2.372232e+02
+3064 0 nan -2.153670e+02
+...[[truncated]]...
+@end example
+
+As you see, in the new @code{SUM-PROJ-IN-SLICE} column, we have a measurement
in each slice: including slices that do not have the label of 198 at all.
+Also, the area used to measure this sum is the same in all slices (similar to
a classical spectrometer's output).
+
+However, there is a big problem: have a look at the sums in slices 3040 and
3041: the values are increasing!
+This is because of the emission in the NII line that also falls over the
projected area of H-alpha.
+This shows the power of IFUs as opposed to classical spectrometers: we can
distinguish between individual lines based on spatial position and do
measurements in 3D!
+
+Finally, in case you want the spectrum with the continuum, you just have to
change the file given to @option{--valuesfile}:
+
+@example
+$ astmkcatalog seg.fits --ids --ra --dec --w3 --sum \
+ --area-in-slice --sum-in-slice --sum-proj-in-slice \
+ --valuesfile=a370-crop.fits \
+ --output=cat-with-continuum.fits
+@end example
+
+@node Extracting a single spectrum and plotting it, Pseudo narrow-band images,
3D measurements and spectra, Detecting lines and extracting spectra in 3D data
+@subsection Extracting a single spectrum and plotting it
+
+In @ref{3D measurements and spectra} we measured the spectra of all the
objects with the MUSE data cube of this demonstration tutorial.
+Let's now write the resulting spectra for our object 198 into a file to view
our measured spectra in TOPCAT for a more visual inspection.
+But we don't want slice numbers (which are specific to MUSE), we want the
horizontal axis to be in Angstroms.
+To do that, we can use the WCS information:
+
+@table @code
+@item CRPIX3
+The ``Coordinate Reference PIXel'' in the 3rd dimension (or slice number of
reference)
+Let's call this @mymath{s_r}.
+@item CRVAL3
+The ``Coordinate Reference VALue'' in the 3rd dimension (the WCS coordinate of
the slice in @code{CRPIX3}.
+Let's call this @mymath{\lambda_r}
+@item CDELT3
+The ``Coordinate DELTa'' in the 3rd dimension, or how much the WCS changes
with every slice.
+Let's call this @mymath{\delta}.
+@end table
+
+@noindent
+To find the @mymath{\lambda} (wavelength) of any slice with number @mymath{s},
we can simply use this equation:
+
+@dispmath{\lambda=\lambda_r+\delta(s-s_r)}
+
+Let's extract these three values from the FITS WCS keywords as shell variables
to automatically do this within Table's column arithmetic.
+Here we are using the technique that is described in @ref{Separate shell
variables for multiple outputs}.
+
+@example
+$ eval $(astfits seg.fits --keyvalue=CRPIX3,CRVAL3,CDELT3 -q \
+ | xargs printf "sr=%s; lr=%s; d=%s;")
+
+## Just for a check:
+$ echo $sr
+1.000000e+00
+$ echo $lr
+4.749679687500000e-07
+$ echo $d
+1.250000000000000e-10
+@end example
+
+Now that we have the necessary constants, we can simply convert the equation
above into @ref{Reverse polish notation} and use column arithmetic to convert
the slice counter into wavelength in the command of @ref{3D measurements and
spectra}.
+
+@example
+$ asttable cat.fits --range=AWAV,8.560e-7,8.570e-7 -O \
+ -carea-in-slice,sum-in-slice,sum-proj-in-slice \
+ --transpose \
+ | asttable -c'arith $1 counter '$sr' - '$d' x '$lr' + f32 swap' \
+ -c2,3 --output=spectrum-obj-198.fits \
+ --colmetadata=1,WAVELENGTH,m,"Wavelength of slice." \
+ --colmetadata=2,"AREA-IN-SLICE",voxel,"No. of voxels."
+
+$ astscript-fits-view spectrum-obj-198.fits
+@end example
+
+Once TOPCAT opens, take the following steps:
+
+@enumerate
+@item
+In the ``Graphics'' menu, select ``Plane plot''.
+@item
+Change @code{AREA-IN-SLICE} to @code{SUM-PROJ-IN-SLICE}.
+@item
+Select the ``Form'' tab.
+@item
+Click on the button with the large green ``+'' button and select ``Add line''.
+@item
+Un-select the ``Mark'' item that was originally selected.
+@end enumerate
+
+@noindent
+Of course, the table in @file{spectrum-obj-198.fits} can be plotted using any
other plotting tool you prefer to use in your scientific papers.
+
+@node Pseudo narrow-band images, , Extracting a single spectrum and plotting
it, Detecting lines and extracting spectra in 3D data
+@subsection Pseudo narrow-band images
+
+In @ref{Continuum subtraction} we subtracted/separated the continuum from the
emission/absorption lines of our galaxy in the MUSE cube.
+Let's visualize the morphology of the galaxy at some of the spectral lines to
see how it looks.
+To do this, we will create pseudo narrow-band 2D images by collapsing the cube
along the third dimension within a certain wavelength range that is optimized
for that flux.
+
+Let's find the wavelength range that corresponds to H-alpha emission we
studied in @ref{Extracting a single spectrum and plotting it}.
+Fortunately MakeCatalog can calculate the minimum and maximum position of each
label along each dimension like the command below.
+If you always need these values, you can includ these columns in the same
MakeCatalog with @option{--sum-proj-in-slice}.
+Here we are running it separately to help you follow the discussion there.
+
+@example
+$ astmkcatalog seg.fits --output=cat-ranges.fits \
+ --ids --min-x --max-x --min-y --max-y --min-z --max-z
+@end example
+
+Let's extract the minimum and maximum positions of this particular object with
the first command and with the second, we'll write them into different shell
variables.
+With the second command, we are writing those six values into a single string
in the format of Crop's @ref{Crop section syntax}.
+For more on the @code{eval}-based shell trick we used here, see @ref{Separate
shell variables for multiple outputs}.
+Finally, we are running Crop and viewing the cropped 3D cube.
+
+@example
+$ asttable cat-ranges.fits --equal=OBJ_ID,198 \
+ -cMIN_X,MAX_X,MIN_Y,MAX_Y,MIN_Z,MAX_Z
+56 101 11 61 3044 3060
+
+$ eval $(asttable cat-ranges.fits --equal=OBJ_ID,198 \
+ -cMIN_X,MAX_X,MIN_Y,MAX_Y,MIN_Z,MAX_Z \
+ | xargs printf "section=%s:%s,%s:%s,%s:%s; ")
+$ astcrop no-continuum.fits --mode=img --section=$section \
+ --output=crop-no-continuum.fits
+$ astscript-fits-view crop-no-continuum.fits
+@end example
+Go through the slices and you will only see this particular region of the full
cube.
+We can now collapse the third dimension of this image into a 2D pseudo-narrow
band image with Arithmetic's @ref{Dimensionality changing operators}:
+@example
+$ astarithmetic crop-no-continuum.fits 3 collapse-sum \
+ --output=collapsed-all.fits
+$ astscript-fits-view collapsed-all.fits
+@end example
+During the collapse, used all the pixels in each slice.
+This is not good for the faint outskirts in the peak of the emission line: the
noise of the slices with less signal decreases the over-all signal-to-noise
ratio in the pseudo-narrow band image.
+So let's set all the pixels that aren't labeled with this object as NaN, then
collapse.
+To do that, we first need to crop the @code{OBJECT} cube in @file{seg.fits}.
+With the second command, please have a look to confirm how the labels change
as a function of wavelength.
+
+@example
+$ astcrop seg.fits -hOBJECTS --mode=img --section=$section \
+ --output=crop-obj.fits
+
+$ astscript-fits-view crop-obj.fits
+@end example
+
+Let's use Arithmetic to first set all the pixels that are not equal to 198 in
@file{collapsed-obj.fits} to be NaN in @file{crop-no-continuum.fits}.
+With the second command, we are opening the two collapsed images together:
+
+@example
+$ astarithmetic crop-no-continuum.fits set-i \
+ crop-obj.fits set-o \
+ i o 198 ne nan where 3 collapse-sum \
+ --output=collapsed-obj.fits
+
+$ astscript-fits-view collapsed-all.fits collapsed-obj.fits \
+ --ds9extra="-lock scalelimits yes -blink"
+@end example
+
+Let it blink a few times and focus on the outskirts: you will see that the
diffuse flux in the outskirts has indeed been preserved better in the
object-based collapsed narrow-band image.
+But this is a little hard to appreciate in the 2D image.
+To see it better practice, let's get the two radial profiles.
+We will approximately assume a position angle of -80 and axis ratio of
0.7@footnote{To derive the axis ratio and position angle automatically, you can
take the following steps. Note that we are not using NoiseChisel because this
crop has been intentionally selected to contain signal, so there is no raw
noise inside of it.
+@example
+$ aststatistics collapsed-all.fits --sky --tilesize=5,5
+$ astarithmetic collapsed-all.fits -h1 collapsed-all_sky.fits -hSKY_STD / 5 gt
\
+ -ocollapsed-lab.fits
+$ astmkcatalog collapsed-lab.fits -h1 --valuesfile=collapsed-all.fits \
+ --position-angle --axis-ratio
+$ asttable collapsed-all_arith_cat.fits -Y
+-78.817 0.694
+@end example
+}.
+With the final command below, we are opening both radial profiles in TOPCAT to
visualize them.
+We are also undersampling the radial profile to have better signal-to-noise
ratio in the outer radii:
+
+@example
+$ astscript-radial-profile collapsed-all.fits \
+ --position-angle=-80 --axis-ratio=0.7 \
+ --undersample=2 --output=collapsed-all-rad.fits
+
+$ astscript-radial-profile collapsed-obj.fits \
+ --position-angle=-80 --axis-ratio=0.7 \
+ --undersample=2 --output=collapsed-obj-rad.fits
+@end example
+
+To view the difference, let's merge the two profiles (the @code{MEAN} column)
into one table and simply print the two profiles beside each other.
+We will then pipe the resulting table containing both columns to a second call
to Gnuastro's Table and use column arithmetic to subtract the two mean values
and divide them by the optimized one (to get the fractional difference):
+
+@example
+$ asttable collapsed-all-rad.fits --catcolumns=MEAN -O \
+ --catcolumnfile=collapsed-obj-rad.fits \
+ | asttable -c1,2,3 -c'arith $3 $2 - $3 /' \
+ --colmetadata=2,MEAN-ALL \
+ --colmetadata=3,MEAN-OBJ \
+ --colmetadata=4,DIFF,frac,"Fractional diff." -YO
+# Column 1: RADIUS [pix ,f32,] Radial distance
+# Column 2: MEAN-ALL [input-units,f32,] Mean of sky subtracted values.
+# Column 3: MEAN-OBJ [input-units,f32,] Mean of sky subtracted values.
+# Column 4: DIFF [frac ,f32,] Fractional diff.
+0.000 436.737 450.256 0.030
+2.000 371.880 384.071 0.032
+4.000 313.429 320.138 0.021
+6.000 275.744 280.102 0.016
+8.000 152.214 154.470 0.015
+10.000 59.311 62.207 0.047
+12.000 18.466 20.396 0.095
+14.000 6.940 8.671 0.200
+16.000 3.052 4.256 0.283
+18.000 1.590 2.848 0.442
+20.000 1.430 2.550 0.439
+22.000 0.838 1.975 0.576
+@end example
+
+@noindent
+As you see, beyond a radius of 10, the last fractional difference column
becomes very large, showing that a lot of signal is missing in the
@code{MEAN-ALL} column.
+For a more visual comparison of the two profiles, you can use the command
below to open both tables in TOPCAT:
+
+@example
+$ astscript-fits-view collapsed-all-rad.fits \
+ collapsed-obj-rad.fits
+@end example
+
+Once TOPCAT has opened take the following steps:
+@enumerate
+@item
+Select @file{collapsed-all-rad.fits}
+@item
+In the ``Graphics'' menu, select ``Plane Plot''.
+@item
+Click on the ``Axes'' side-bar (by default, at the bottom half of the window),
and click on ``Y Log'' to view the vertical axis in logarithmic scale.
+@item
+In the ``Layers'' menu, select ``Add Position Control''.
+You will see that at the bottom half, a new scatter plot information is
displayed.
+@item
+Click on the scroll-down menu infront of ``Table'' and select @file{2:
collapsed-obj-rad.fits}.
+Afterwards, you will see the optimized pseudo-narrow-band image radial profile
as blue points.
+@end enumerate
@node Installation, Common program behavior, Tutorials, Top
@chapter Installation
@@ -8065,7 +8951,7 @@ Therefore its headers (and libraries) are not needed.
@cindex Numpy
@cindex Python3
Python is a high-level programming language and Numpy is the most commonly
used library within Python to add multi-dimensional arrays and matrices.
-If version 3 of Python is available with a corresponding Numpy Library,
Gnuastro's library will be built with some Python-related helper functions.
+If you configure Gnuastro with @option{--with-python} @emph{and} version 3 of
Python is available with a corresponding Numpy Library, Gnuastro's library will
be built with some Python-related helper functions.
Python wrappers for Gnuastro's library (for example, `pyGnuastro') can use
these functions when being built from source.
For more on Gnuastro's Python helper functions, see @ref{Python interface}.
@@ -10629,9 +11515,9 @@ Let's review the solution (in more detail):
@item
@cindex Standard input
@cindex @command{xargs} (extended arguments)
-We pipe the output into the @option{xargs}@footnote{For more on
@command{xargs}, see @url{https://en.wikipedia.org/wiki/Xargs}. In short
@command{xargs} will take the standard input (from the pipe in this scenario)
and put it as arguments of the next program.
-In other words, it is good for programs that don't take input from standard
input (@command{printf} in this case; but also includes others like
@command{cp}, @command{rm}, or @command{echo}).} (extended arguments).
-@command{xargs} puts the two numbers it gets from the pipe, as arguments for
@command{printf} (formatted print) because @command{printf} doesn't take input
from pipes.
+We pipe the output into @command{xargs}@footnote{For more on @command{xargs},
see @url{https://en.wikipedia.org/wiki/Xargs}.
+It will take the standard input (from the pipe in this scenario) and put it as
arguments of the next program (@command{printf} in this scenario).
+In other words, it is good for programs that don't take input from standard
input (@command{printf} in this case; but also includes others like
@command{cp}, @command{rm}, or @command{echo}).} (extended arguments) which
puts the two numbers it gets from the pipe, as arguments for @command{printf}
(formatted print; because @command{printf} doesn't take input from pipes).
@item
Within the @command{printf} call, we write the values after putting a variable
name and equal-sign, and in between them we put a @key{;} (as if it was a shell
command).
The @code{%s} tells @command{printf} to print each input as a string (not to
interpret it as a number and loose precision).
@@ -10663,6 +11549,8 @@ $ echo $my_std
This @command{eval}-based solution has been tested in in GNU Bash, Dash and
Zsh and it works nicely in them (is ``portable'').
This is because the constructs used here are pretty low-level (and widely
available).
+For examples usages of this technique, see the following sections:
@ref{Extracting a single spectrum and plotting it} and @ref{Pseudo narrow-band
images}.
+
@node Configuration files, Getting help, Command-line, Common program behavior
@section Configuration files
@@ -12707,7 +13595,7 @@ To stop as soon as an error occurs, run with
@option{--quitonerror}.
@item -p
@itemx --printallkeys
-Print the full meta data (keywords, values, units and comments) in the
specified FITS extension (HDU).
+Print the full metadata (keywords, values, units and comments) in the
specified FITS extension (HDU).
If this option is called along with any of the other keyword editing commands,
as described above, all other editing commands take precedence to this.
Therefore, it will print the final keywords after all the editing has been
done.
@@ -14462,13 +15350,13 @@ To address these problems, the FITS standard has
defined the concept of ``vector
Within each row of a single vector column, we can store any number of
datapoints (like the MUSE spectra above or the full radial profile of each
galaxy).
All the values in a vector column have to have the same @ref{Numeric data
types}, and the number of elements within each vector column is the same for
all rows.
-By grouping conceptually similar data points (like a spectra) in one vector
column, we can significantly reduce the number of columns and make it much more
managable, without loosing any information!
+By grouping conceptually similar data points (like a spectrum) in one vector
column, we can significantly reduce the number of columns and make it much more
managable, without loosing any information!
To demonstrate the vector column features of Gnuastro's Table program, let's
start with a randomly generated small (5 rows and 3 columns) catalog.
This will allows us to show the outputs of each step here, but you can apply
the same concept to vectors with any number of colums.
With the command below, we use @code{seq} to generate a single-column table
that is piped to Gnuastro's Table program.
-Table then uses column arithmetic to generate three columns with random values
from that base row (for more, see @ref{Column arithmetic}).
-Each column has with a larger noise sigma.
+Table then uses column arithmetic to generate three columns with random values
from that column (for more, see @ref{Column arithmetic}).
+Each column becomes noisy, with standard deviations of 2, 5 and 10.
Finally, we will add metadata to each column, giving each a different name
(using names is always the best way to work with columns):
@example
@@ -14486,18 +15374,18 @@ With the command below, let's have a look at the
table.
When you run it, you will have a different random number generator seed, so
the numbers will be slightly different.
For making reproducible random numbers, see @ref{Generating random numbers}.
The @option{-Y} option is used for more easily readable numbers (without it,
floating point numbers are written in scientific notation, for more see
@ref{Printing floating point numbers}) and with the @option{-O} we are asking
Table to also print the metadata.
-For more on Table's options, see @ref{Invoking asttable} and for seeing how
the short options can be merged, see @ref{Options}.
+For more on Table's options, see @ref{Invoking asttable} and for seeing how
the short options can be merged (such that @option{-Y -O} is identical to
@option{-YO}), see @ref{Options}.
@example
$ asttable table.fits -YO
# Column 1: abc [none,f32,] First column.
# Column 2: def [none,f32,] Second column.
# Column 3: ghi [none,f32,] Third column.
--2.694 -9.130 +6.865
-+3.166 +4.239 +18.386
-+4.709 +0.561 +1.817
--0.338 +4.927 -5.010
-+7.291 +5.541 +3.311
+1.074 5.535 -4.464
+0.606 -2.011 15.397
+1.475 1.811 5.687
+2.248 7.663 -7.789
+6.355 17.374 6.767
@end example
We see that indeed, it has three columns, with our given names.
@@ -14509,18 +15397,18 @@ As the name suggests, @option{--tovector} will merge
the rows of the two columns
$ asttable table.fits -YO --tovector=def,ghi
# Column 1: abc [none,f32 ,] First column.
# Column 2: def-VECTOR [none,f32(2),] Vector by merging multiple cols.
--2.694 -9.130 +6.865
-+3.166 +4.239 +18.386
-+4.709 +0.561 +1.817
--0.338 +4.927 -5.010
-+7.291 +5.541 +3.311
+1.074 5.535 -4.464
+0.606 -2.011 15.397
+1.475 1.811 5.687
+2.248 7.663 -7.789
+6.355 17.374 6.767
@end example
@cindex Tokens
If you ignore the metadata, this doesn't seem to have changed anything!
You see that each line of numbers still has three ``tokens'' (to distinguish
them from ``columns'').
But once you look at the metadata, you only see metadata for two columns, not
three.
-If you look closely, the numeric data type of the newly added fourth column is
`@code{f32(2)}' (look above, previously it was @code{f32}).
+If you look closely, the numeric data type of the newly added fourth column is
`@code{f32(2)}' (look above; previously it was @code{f32}).
The @code{(2)} shows that the second column contains two numbers/tokens not
one.
If your vector column consisted of 3681 numbers, this would be
@code{f32(3681)}.
Looking again at the metadata, we see that @option{--tovector} has also
created a new name and comments for the new column.
@@ -14533,7 +15421,7 @@ We can get a first confirmation by looking at the
table's metadata in the second
@example
$ asttable table.fits -YO --tovector=def,ghi --output=vec.fits \
- --colmetadata=2,defghi,nounits,"New vector column"
+ --colmetadata=2,vector,nounits,"New vector column."
$ asttable vec.fits -i
--------
@@ -14542,56 +15430,57 @@ vec.fits (hdu: 1)
No.Name Units Type Comment
------- ----- ---- -------
1 abc none float32 First column.
-2 defghi nounits float32(2) New vector column
+2 vector nounits float32(2) New vector column.
--------
Number of rows: 5
+--------
@end example
@noindent
-A more robust confirmation would be to print the values in the newly added
@code{defghi} column.
-As expected, asking for a single column with @option{--column} (or
@option{-c}) will given us two numbers per row/line.
+A more robust confirmation would be to print the values in the newly added
@code{vector} column.
+As expected, asking for a single column with @option{--column} (or
@option{-c}) will given us two numbers per row/line (instead of one!).
@example
-$ asttable vec.fits -c defghi -YO
-# Column 1: defghi [nounits,f32(2),] New vector column
--9.130 +6.865
-+4.239 +18.386
-+0.561 +1.817
-+4.927 -5.010
-+5.541 +3.311
+$ asttable vec.fits -c vector -YO
+# Column 1: vector [nounits,f32(2),] New vector column.
+ 5.535 -4.464
+-2.011 15.397
+ 1.811 5.687
+ 7.663 -7.789
+ 17.374 6.767
@end example
If you want to keep the original single-valued columns that went into the
vector column, you can use the @code{--keepvectfin} option (read it as ``KEEP
VECtor To/From Inputs''):
@example
$ asttable table.fits -YO --tovector=def,ghi --keepvectfin \
- --colmetadata=4,defghi,nounits,"New vector column"
+ --colmetadata=4,vector,nounits,"New vector column."
# Column 1: abc [none ,f32 ,] First column.
# Column 2: def [none ,f32 ,] Second column.
# Column 3: ghi [none ,f32 ,] Third column.
-# Column 4: defghi [nounits,f32(2),] New vector column
--2.694 -9.130 +6.865 -9.130 +6.865
-+3.166 +4.239 +18.386 +4.239 +18.386
-+4.709 +0.561 +1.817 +0.561 +1.817
--0.338 +4.927 -5.010 +4.927 -5.010
-+7.291 +5.541 +3.311 +5.541 +3.311
+# Column 4: vector [nounits,f32(2),] New vector column.
+1.074 5.535 -4.464 5.535 -4.464
+0.606 -2.011 15.397 -2.011 15.397
+1.475 1.811 5.687 1.811 5.687
+2.248 7.663 -7.789 7.663 -7.789
+6.355 17.374 6.767 17.374 6.767
@end example
Now that you know how to create vector columns, let's assume you have the
inverse scenario: you want to extract one of the values of a vector column into
a separate single-valued column.
To do this, you can use the @option{--fromvector} option.
-The @option{--fromvector} option takes the name (or counter) of a vector
column, followed by any number of integer counters.
+The @option{--fromvector} option takes the name (or counter) of a vector
column, followed by any number of integer counters (counting from 1).
It will extract those elements into separate single-valued columns.
For example, let's assume you want to extract the second element of the
@code{defghi} column in the file you made before:
@example
-$ asttable vec.fits --fromvector=defghi,2 -YO
+$ asttable vec.fits --fromvector=vector,2 -YO
# Column 1: abc [none ,f32,] First column.
-# Column 2: defghi-2 [nounits,f32,] New vector column
--2.694 +6.865
-+3.166 +18.386
-+4.709 +1.817
--0.338 -5.010
-+7.291 +3.311
+# Column 2: vector-2 [nounits,f32,] New vector column.
+1.074 -4.464
+0.606 15.397
+1.475 5.687
+2.248 -7.789
+6.355 6.767
@end example
@noindent
@@ -14601,11 +15490,13 @@ This feature is useful in scenarios where you want to
select some rows based on
@cartouche
@noindent
@strong{Vector columns and FITS ASCII tables:} As mentioned above, the FITS
standard only recognizes vector columns in its Binary table format (the default
FITS table format in Gnuastro).
-You can use the @option{--tableformat=fits-ascii} option to write your tables
in the FITS ASCII format (see @ref{Input output options}).
+You can still use the @option{--tableformat=fits-ascii} option to write your
tables in the FITS ASCII format (see @ref{Input output options}).
In this case, if a vector column is present, it will be written as separate
single-element columns to avoid loosing information (as if you run called
@option{--fromvector} on all the elements of the vector column).
A warning is printed if this occurs.
@end cartouche
+For an application of the vector column concepts introduced here on MUSE data,
see the 3D data cube tutorial and in paraticular these two sections: @ref{3D
measurements and spectra} and @ref{Extracting a single spectrum and plotting
it}.
+
@node Column arithmetic, Operation precedence in Table, Vector columns, Table
@subsection Column arithmetic
@@ -14663,9 +15554,9 @@ When the columns have descriptive names, the
command/script actually becomes muc
It is also independent of the low-level table structure: for the second
command, the column numbers of the @code{AWAV} and @code{SPECTRUM} columns in
@file{table.fits} is irrelevant.
Column arithmetic changes the values of the data within the column.
-So the old column meta data cannot be used any more.
+So the old column metadata cannot be used any more.
By default the output column of the arithmetic operation will be given a
generic metadata (for example, its name will be @code{ARITH_1}, which is hardly
useful!).
-But meta data are critically important and it is good practice to always have
short, but descriptive, names for each columns, units and also some comments
for more explanation.
+But metadata are critically important and it is good practice to always have
short, but descriptive, names for each columns, units and also some comments
for more explanation.
To add metadata to a column, you can use the @option{--colmetadata} option
that is described in @ref{Invoking asttable} and @ref{Operation precedence in
Table}.
Since the arithmetic expressions are a value to @option{--column}, it does not
necessarily have to be a separate option, so the commands above are also
identical to the command below (note that this only has one @option{-c} option).
@@ -14862,6 +15753,17 @@ The Table program can do many operations on the rows
and columns of the input ta
In this section we will describe which operation is done before/after which
operation.
Knowing this precedence table is important to avoid confusion when you ask for
more than one operation.
For a description of each option, please see @ref{Invoking asttable}.
+By default, column-based operations will be done first.
+You can ask for switching to row-based operations to be done first, using the
@option{--rowfirst} option.
+
+@cartouche
+@noindent
+@strong{Pipes for different precedence:} It may happen that your desired
series of operations cannot be done with the precedence mentioned below (in one
command).
+In this case, you can pipe the output of one call to @command{asttable} to
another @command{asttable}.
+Just don't forget to give @option{-O} (or @option{--colinfoinstdout}) to the
first instance (so the column metadata are also passed to the next instance).
+Without metadata, all numbers will be read as double-precision (see
@ref{Gnuastro text table format}; recall that piping is done in plain text
format), vector columns will be broken into single-valued columns, and column
names, units and comments will be lost.
+At the end of this section, there is an example of doing this.
+@end cartouche
@table @asis
@item Column information (@option{--information} or @option{-i})
@@ -14874,11 +15776,17 @@ This can therefore be called at the end of an
arbitrarily long Table command onl
When this option is given, only the columns given to this option (from the
main input) will be used for all future steps.
When @option{--column} (or @option{-c}) is not given, then all the main
input's columns will be used in the next steps.
-@item Column(s) from other file(s) (@option{--catcolumnfile} and
@option{--catcolumnhdu}, @option{--catcolumns})
-When column concatenation (addition) is requested, columns from other tables
(in other files, or other HDUs of the same FITS file) will be added after the
existing columns read from the main input.
-In one command, you can call these options multiple times to allow addition of
columns from many files.
+@item Column-based operations
+By default the following column-based operations will be done before the
row-based operations in the next item.
+If you need to give precedence to row-based operations, use
@option{--rowfirst}.
+
+@table @asis
+
+@item Column(s) from other file(s): @option{--catcolumnfile}
+When column concatenation (addition) is requested, columns from other tables
(in other files, or other HDUs of the same FITS file) will be added after the
existing columns are read from the main input.
+In one command, you can call @option{--catcolumnfile} multiple times to allow
addition of columns from many files.
-The rest of the operations below are done on the rows, therefore you can merge
the columns of various tables into one table, then start adding/limiting the
rows of the output.
+Therefore you can merge the columns of various tables into one table in this
step (at the start), then start adding/limiting the rows, or building vector
columns, .
If any of the row-based operations below are requested in the same
@code{asttable} command, they will also be applied to the rows of the added
columns.
However, the conditions to keep/reject rows can only be applied to the rows of
the columns in main input table (not the columns that are added with these
options).
@@ -14886,9 +15794,27 @@ However, the conditions to keep/reject rows can only
be applied to the rows of t
Once all the input columns are read into memory, if any of them are vectors,
you can extract a single-valued column from the vector columns at this stage.
For more on vector columns, see @ref{Vector columns}.
-@item Rows from other file(s) (@option{--catrowfile} and @option{--catrowhdu})
+@item Creating vector columns (@option{--tovector})
+After column arithmetic, there is no other way to add new columns so the
@option{--tovector} operator is applied at this stage.
+You can use it to merge multiple columns that are available in this stage to a
single vector column.
+For more, see @ref{Vector columns}.
+
+@item Column arithmetic
+Once the final rows are selected in the requested order, column arithmetic is
done (if requested).
+For more on column arithmetic, see @ref{Column arithmetic}.
+
+@end table
+
+
+@item Row-based operations
+Row-based operations only work within the rows of existing columns when they
are activated.
+By default row-based operations are activated after column-based operations
(which are mentioned above).
+If you need to give precedence to row-based operations, use
@option{--rowfirst}.
+
+@table @asis
+@item Rows from other file(s) (@option{--catrowfile})
With this feature, you can import rows from other tables (in other files, or
other HDUs of the same FITS file).
-The same column selection of @option{--column} is applied to the tables given
here.
+The same column selection of @option{--column} is applied to the tables given
to this option.
The column metadata (name, units and comments) will be taken from the main
input.
Two conditions are mandatory for adding rows:
@itemize
@@ -14896,37 +15822,42 @@ Two conditions are mandatory for adding rows:
The number of columns used from the new tables must be equal to the number of
columns in memory, by the time control reaches here.
@item
The data type of each column (see @ref{Numeric data types}) should be the same
as the respective column in memory by the time control reaches here.
-If the data types are different, you can use the type conversion operators of
Table's column arithmetic on the inputs in a separate command first (see
@ref{Numerical type conversion operators} and @ref{Column arithmetic}).
+If the data types are different, you can use the type conversion operators of
column arithmetic which has higher precedence (and will therefore be applied
before this by default).
+For more on type conversion, see @ref{Numerical type conversion operators} and
@ref{Column arithmetic}).
@end itemize
@item Row selection by value in a column
+The following operations select rows based on the values in them.
+A more complete description of each of these options is given in @ref{Invoking
asttable}.
+
@itemize
@item
-@option{--range}: only keep rows within a certain interval in given column.
+@option{--range}: only keep rows where the value in the given column is within
a certain interval.
@item
-@option{--inpolygon}: only keep rows within the polygon of @option{--polygon}.
+@option{--inpolygon}: only keep rows where the value is within the polygon of
@option{--polygon}.
@item
@option{--outpolygon}: only keep rows outside the polygon of
@option{--polygon}.
@item
-@option{--equal}: only keep rows with specified value in given column.
+@option{--equal}: only keep rows with an specified value in given column.
@item
@option{--notequal}: only keep rows without specified value in given column.
@item
@option{--noblank}: only keep rows that are not blank in the given column(s).
@end itemize
-These options take certain column(s) as input and remove some rows from the
full table (all columns), based on the given limitations.
-They can be called any number of times (to limit the final rows based on
values in different columns for example).
+
+These options can be called any number of times (to limit the final rows based
on values in different columns for example).
Since these are row-rejection operations, their internal order is irrelevant.
In other words, it makes no difference if @option{--equal} is called before or
after @option{--range} for example.
As a side-effect, because NaN/blank values are defined to fail on any
condition, these operations will also remove rows with NaN/blank values in the
specified column they are checking.
Also, the columns that are used for these operations do not necessarily have
to be in the final output table (you may not need the column after doing the
selection based on it).
-Even though these options are applied after merging columns from other tables,
currently their condition-columns can only come from the main input table.
-In other words, even though the rows of the added columns (from another file)
will also be selected with these options, the condition to keep/reject rows
cannot be taken from the newly added columns.
+By default, these options are applied after merging columns from other tables.
+However, currently, the column given to these options can only come from the
main input table.
+If you need to apply these operations on columns from
@option{--catcolumnfile}, pipe the output of one instance of Table with
@option{--catcolumnfile} into another instance of Table as suggested in the box
above this list.
-These options are applied first because the speed of later operations can be
greatly affected by the number of rows.
-For example, if you also call the @option{--sort} option, and your row
selection will result in 50 rows (from an input of 1000 rows), limiting the
number of rows can greatly speed up the sorting in your final output.
+These row-based operations options are applied first because the speed of
later operations can be greatly affected by the number of rows.
+For example, if you also call the @option{--sort} option, and your row
selection will result in 50 rows (from an input of 10000 rows), limiting the
number of rows first will greatly speed up the sorting in your final output.
@item Sorting (@option{--sort})
Sort of the rows based on values in a certain column.
@@ -14946,24 +15877,21 @@ The column to sort by can only come from the main
input table columns (not colum
These options limit/select rows based on their position within the table (not
their value in any certain column).
-@item Column arithmetic
-Once the final rows are selected in the requested order, column arithmetic is
done (if requested).
-For more on column arithmetic, see @ref{Column arithmetic}.
-
-@item Creating vector columns (@option{--tovector})
-After column arithmetic, there is no other way to add new columns so the
@option{--tovector} operator is applied at this stage.
-You can use it to merge multiple columns that are available in this stage to a
single vector column.
-For more, see @ref{Vector columns}.
+@item Transpose vector columns (@option{--transpose})
+Transposing vector columns will not affect the number or metadata of columns,
it will just re-arrange them in their 2D structure.
+As a result, after transposing, the number of rows changes, as well as the
number of elements in each vector column.
+See the description of this option in @ref{Invoking asttable} for more (with
an example).
+@end table
@item Column metadata (@option{--colmetadata})
-Changing column metadata is necessary after column arithmetic or adding new
columns from other tables (that were done above).
+Once the structure of the final table is set, you can set the column metadata
just before finishing.
@item Output row selection (@option{--noblankend})
Only keep the output rows that do not have a blank value in the given
column(s).
For example, you may need to apply arithmetic operations on the columns
(through @ref{Column arithmetic}) before rejecting the undesired rows.
After the arithmetic operation is done, you can use the @code{where} operator
to set the non-desired columns to NaN/blank and use @option{--noblankend}
option to remove them just before writing the output.
In other scenarios, you may want to remove blank values based on columns in
another table.
-You can also use the modified metadata of the previous steps to use updated
names!
+To help in readability, you can also use the final column names that you set
with @option{--colmetadata}!
See the example below for applying any generic value-based row selection based
on @option{--noblankend}.
@end table
@@ -14971,9 +15899,9 @@ As an example, let's review how Table interprets the
command below.
We are assuming that @file{table.fits} contains at least three columns:
@code{RA}, @code{DEC} and @code{PARAM} and you only want the RA and Dec of the
rows where @mymath{p\times 2<5} (@mymath{p} is the value of each row in the
@code{PARAM} column).
@example
-asttable table.fits -cRA,DEC --noblankend=MULTIP \
- -c'arith PARAM 2 x set-i i i 5 gt nan where' \
- --colmetadata=3,MULTIP,unit,"Description of column"
+$ asttable table.fits -cRA,DEC --noblankend=MULTIP \
+ -c'arith PARAM 2 x set-i i i 5 gt nan where' \
+ --colmetadata=3,MULTIP,unit,"Description of column"
@end example
@noindent
@@ -14995,14 +15923,12 @@ The lowest precedence operation is
@option{--noblankend=MULTIP}.
So only rows that are not blank/NaN in the @code{MULTIP} column are kept.
@item
Finally, the output table (with three columns) is written to the command-line.
-If you also want to print the column metadata, you can use the
@option{--colinfoinstdout} option.
+If you also want to print the column metadata, you can use the @option{-O} (or
@option{--colinfoinstdout}) option.
Alternatively, if you want the output in a file, you can use the
@option{--output} option to save the table in FITS or plain-text format.
@end enumerate
-@cartouche
-@noindent
-@strong{Out of precedence:} It may happen that your desired operation needs a
separate precedence.
-In this case you can pipe the output of Table into another call of Table and
use the @option{--colinfoinstdout} option to preserve the metadata between the
two calls.
+It may happen that your desired operation needs a separate precedence.
+In this case you can pipe the output of Table into another call of Table and
use the @option{-O} (or @option{--colinfoinstdout}) option to preserve the
metadata between the two calls.
For example, let's assume that you want to sort the output table from the
example command above based on the new @code{MULTIP} column.
Since sorting is done prior to column arithmetic, you cannot do it in one
command, but you can circumvent this limitation by simply piping the output
(including metadata) to another call to Table:
@@ -15013,7 +15939,6 @@ asttable table.fits -cRA,DEC --noblankend=MULTIP
--colinfoinstdout \
--colmetadata=3,MULTIP,unit,"Description of column" \
| asttable --sort=MULTIP --output=selected.fits
@end example
-@end cartouche
@node Invoking asttable, , Operation precedence in Table, Table
@subsection Invoking Table
@@ -15209,6 +16134,30 @@ See @option{--catcolumnfile} for more.
@item --catcolumnrawname
Do Not modify the names of the concatenated (appended) columns, see
description in @option{--catcolumnfile}.
+@item --transpose
+Transpose (as in a matrix) the given vector column(s) individually.
+When this operation is done (see @ref{Operation precedence in Table}), only
vector columns of the same data type and with the same number of elements
should exist in the table.
+A usage of this operator is presented in the IFU spectroscopy tutorial in
@ref{Extracting a single spectrum and plotting it}.
+
+As a generic example, see the commands below.
+The @file{in.txt} table below has two vector columns (each with three
elements) in two rows.
+After running @command{asttable} with @option{--transpose}, you can see how
the vector columns have two elements per row (@code{u8(3)} has been replaced by
@code{u8(2)}), and that the table now has three rows.
+
+@example
+$ cat in.txt
+# Column 1: abc [nounits,u8(3),] First vector colum
+# Column 2: def [nounits,u8(3),] Second vector colum
+111 112 113 211 212 213
+121 122 123 221 222 223
+
+$ asttable in.txt --transpose -O
+# Column 1: abc [nounits,u8(2),] First vector colum
+# Column 2: def [nounits,u8(2),] Second vector colum
+111 121 211 221
+112 122 212 222
+113 123 213 223
+@end example
+
@item --fromvector=STR,INT[,INT[,INT]]
Extract the given tokens/elements from the given vector column into separate
single-valued columns.
The input vector column can be identified by its name or counter, see
@ref{Selecting table columns}.
@@ -16664,7 +17613,7 @@ When only one crop is desired, the value to
@option{--output} will be read as a
If no output is specified or if it is a directory, the output file name will
follow the automatic output names of Gnuastro, see @ref{Automatic output}: The
string given to @option{--suffix} will be replaced with the @file{.fits} suffix
of the input.
@end itemize
-By default, as suggested by the FITS standard and implemented in all Gnuastro
programs, the first/primary extension of the output files will only contain
meta data.
+By default, as suggested by the FITS standard and implemented in all Gnuastro
programs, the first/primary extension of the output files will only contain
metadata.
The cropped images/cubes will be written into the 2nd HDU of their respective
FITS file (which is actually counted as @code{1} because HDU counting starts
from @code{0}).
However, if you want the cropped data to be written into the primary (0-th)
HDU, run Crop with the @option{--primaryimghdu} option.
@@ -16719,7 +17668,7 @@ If the output file doesn't exist, this option is
redundant.
@item --primaryimghdu
Write the output into the primary (0-th) HDU/extension of the output.
-By default, like all Gnuastro's default outputs, no data is written in the
primary extension because the FITS standard suggests keeping that extension
free of data and only for meta data.
+By default, like all Gnuastro's default outputs, no data is written in the
primary extension because the FITS standard suggests keeping that extension
free of data and only for metadata.
@item -t
@itemx --oneelemstdout
@@ -25117,6 +26066,7 @@ When the object cannot be represented as an ellipse,
this interpretation breaks
+
@node Adding new columns to MakeCatalog, MakeCatalog measurements, Measuring
elliptical parameters, MakeCatalog
@subsection Adding new columns to MakeCatalog
@@ -25210,7 +26160,7 @@ Columns/options that are unique to one catalog (only
objects, or only clumps), a
* Surface brightness measurements:: Various ways to measure surface
brightness.
* Morphology measurements nonparametric:: Non-parametric morphology.
* Morphology measurements elliptical:: Elliptical morphology measurements.
-* Spectra measurement in a cube:: How to get the value of a label across all
slices.
+* Measurements per slice spectra:: Measurements on each slice (like spectra).
@end menu
@node Identifier columns, Position measurements in pixels, MakeCatalog
measurements, MakeCatalog measurements
@@ -25761,7 +26711,7 @@ This is only available for 3-dimensional datasets.
When working with Integral Field Unit (IFU) datasets, this projection onto the
first two dimensions would be a narrow-band image.
@end table
-@node Morphology measurements elliptical, Spectra measurement in a cube,
Morphology measurements nonparametric, MakeCatalog measurements
+@node Morphology measurements elliptical, Measurements per slice spectra,
Morphology measurements nonparametric, MakeCatalog measurements
@subsubsection Morphology measurements (elliptical)
When your target objects are sufficiently ellipse-like, you can use the
measurements below to quantify the various parameters of the ellipse.
@@ -25795,33 +26745,89 @@ The geometric (ignoring pixel values) axis ratio of
the profile, assuming it is
The geometric (ignoring pixel values) angle of the semi-major axis with the
first FITS axis in degrees.
@end table
-@node Spectra measurement in a cube, , Morphology measurements elliptical,
MakeCatalog measurements
-@subsubsection Spectra measurement in a cube
+@node Measurements per slice spectra, , Morphology measurements elliptical,
MakeCatalog measurements
+@subsubsection Measurements per slice (spectra)
+@cindex Spectrum
@cindex 3D data-cubes
@cindex Cubes (3D data)
@cindex IFU: Integral Field Unit
@cindex Integral field unit (IFU)
@cindex Spectrum (of astronomical source)
-MakeCatalog can also do multi-valued measurements per label.
-Currently the only such measurement is the creation of spectra from 3D data
cubes as discussed below:
+When the input is a 3D data cube, MakeCatalog has the following multi-valued
measurements per label.
+For a tutorial on how to use these options and interpret their values, see
@ref{Detecting lines and extracting spectra in 3D data}.
+
+These options will do measurements on each 2D slice of the input 3D cube;
hence the common the format of @code{--*-in-slice}.
+Each slice usually corresponds to a certain wavelength, you can also think of
these measurements as spectra.
+
+For each row (input label), each of the columns described here will contain
multiple values as a vector column.
+The number of measurements in each column is the number of slices in the cube,
or the size of the cube along the third dimension.
+To learn more about vector columns and how to manipulate them, see @ref{Vector
columns}.
+For example usage of these columns in the tutorial above, see @ref{3D
measurements and spectra} and @ref{Extracting a single spectrum and plotting
it}.
+
+@noindent
+There are two ways to do each measurement on a slice for each label:
+@table @asis
+@item Only label
+The measurement will only be done on the voxels in the slice that are
assciated to that label.
+These types of per-slice measurement therefore have the following properties:
+@itemize
+@item
+This will only be a measurement of that label and will not be affected by any
other label.
+@item
+The number of voxels used in each slice can be different (usually only one or
two voxels at the two extremes of the label (along the third dimension), and
many in the middle.
+@item
+Since most labels are localized along the third dimension (maybe only covering
20 slices out of thousands!), many of the measurements (on slices where the
label doesn't exist) will be NaN (for the sum measurements for example) or 0
(for the area measurements).
+@end itemize
+@item Projected label
+MakeCatalog will first project the 3D label into a 2D surface (along the third
dimension) to get its 2D footprint.
+Afterwards, all the voxels in that 2D footprint will be measured all slices.
+All these measurements will have a @option{-proj-} component in their name.
+These types of per-slice measurement therefore has the following properties:
+
+@itemize
+@item
+A measurement will be done on each slice of the cube.
+@item
+All measurements will be done on the same surface area.
+@item
+Labels can overlap when they are projected onto the first two FITS dimensions
(the spatial coordinates, not spectral).
+As a result, other emission lines or objects may contaminate the resulting
spectrum for each label.
+@end itemize
+
+To help separate other labels, MakeCatalog can do a third type of measurement
on each slice: measurements on the voxels that belong to other labels but
overlap with the 2D projection.
+This can be used to see how much your projected measurement is affected by
other emission sources (on the projected spectra) and also if multiple lines
(labeled regions) belong to the same physical object.
+These measurements contain @code{-other-} in their name.
+@end table
@table @option
-@item --spectrum
-Generate a spectrum (measurement along the first two FITS dimensions) for each
label when the input dataset is a 3D data cube.
-With this option, a seprate table/spectrum will be generated for every label.
-If the output is a FITS file, each label's spectrum will be written into an
extension of that file with a standard name of @code{SPECTRUM_NN} (the label
will be replaced with @code{NN}).
-If the output is a plain text file, each label's spectrum will be written into
a separate file with the suffix @file{spec-NN.txt}.
-See @ref{MakeCatalog output} for more on specifying MakeCatalog's output file.
-
-The spectra will contain one row for every slice (third FITS dimension) of the
cube.
-Since the physical nature of the third dimension is different, two types of
spectra (along with their errors) are measured:
-1) Sum of values in each slice that only have the requested label.
-2) Sum of values on the 2D projection of the whole label (the area of this
projection can be requested with the @option{--area-xy} column above).
-
-Labels can overlap when they are projected onto the first two FITS dimensions
(the spatial domain).
-To help separate them, MakeCatalog does a third measurement on each slice: the
area, sum of values and error of all pixels that belong to other labels but
overlap with the 2D projection.
-This can be used to see how reliable the emission line measurement is (on the
projected spectra) and also if multiple lines (labeled regions) belong to the
same physical object.
+
+@item --sum-in-slice
+[Only label] Sum of values in each slice.
+
+@item --sum-err-in-slice
+[Only label] Error in '--sum-in-slice'.
+
+@item --area-in-slice
+[Only label] Number of labeled in each slice.
+
+@item --sum-proj-in-slice
+[Projected label] Sum of projected area in each slice.
+
+@item --area-proj-in-slice:
+[Projected label] Number of voxels that are used in
@option{--sum-proj-in-slice}.
+
+@item --sum-proj-err-in-slice
+[Projected label] Error of @option{--sum-proj-in-slice}.
+
+@item --area-other-in-slice
+[Projected label] Area of other label in projected area on each slice.
+
+@item --sum-other-in-slice
+[Projected label] Sum of other label in projected area on each slice.
+
+@item --sum-other-err-in-slice:
+[Projected label] Area in @option{--sum-other-in-slice}.
@end table
@@ -28168,9 +29174,9 @@ The focus here is obtaining a physical insight into
these equations (mainly for
There are many books thoroughly deriving and proving all the equations with
all possible initial conditions and assumptions for any abstract universe,
interested readers can study those books.
@menu
-* Distance on a 2D curved space:: Distances in 2D for simplicity
+* Distance on a 2D curved space:: Distances in 2D for simplicity.
* Extending distance concepts to 3D:: Going to 3D (our real universe).
-* Invoking astcosmiccal:: How to run CosmicCalculator
+* Invoking astcosmiccal:: How to run CosmicCalculator.
@end menu
@node Distance on a 2D curved space, Extending distance concepts to 3D,
CosmicCalculator, CosmicCalculator
@@ -28389,7 +29395,7 @@ $ astcosmiccal --redshift=0.8 --volume
## Print redshift and age of universe when Lyman-alpha line is
## at 6000 angstrom (another way to specify redshift).
-$ astcosmiccal --obsline=lyalpha,6000 --age
+$ astcosmiccal --obsline=Ly-alpha,6000 --age
## Print luminosity distance, angular diameter distance and age
## of universe in one row at redshift 0.4
@@ -28401,7 +29407,7 @@ $ astcosmiccal -l0.7 -m0.3 -z2.1
## Print wavelength of all pre-defined spectral lines when
## Lyman-alpha is observed at 4000 Angstroms.
-$ astcosmiccal --obsline=lyalpha,4000 --listlinesatz
+$ astcosmiccal --obsline=Ly-alpha,4000 --listlinesatz
@end example
The input parameters (current matter density, etc.) can be given as
command-line options or in the configuration files, see @ref{Configuration
files}.
@@ -28467,177 +29473,18 @@ Radiation density divided by the critical density in
the current Universe (@myma
@cindex Wavelength, rest-frame
Find the redshift to use in next steps based on the rest-frame and observed
wavelengths of a line.
This option is thus an alternative to @code{--redshift} or @code{--velocity},
it cannot be used with them.
-Wavelengths are assumed to be in Angstroms.
+
The first argument identifies the line.
-It can be one of the standard names below, or any rest-frame wavelength in
Angstroms.
+It can be one of the standard names, or any rest-frame wavelength in Angstroms.
The second argument is the observed wavelength of that line.
-For example, @option{--obsline=lyalpha,6000} is the same as
@option{--obsline=1215.64,6000}.
-
-The pre-defined names are listed below, sorted from red (longer wavelength) to
blue (shorter wavelength).
-You can get this list on the command-line with the @option{--listlines}.
-
-@table @code
-@item siired
-[6731@AA{}] SII doublet's redder line.
-
-@item sii
-@cindex Doublet: SII
-@cindex SII doublet
-[6724@AA{}] SII doublet's mean center at .
-
-@item siiblue
-[6717@AA{}] SII doublet's bluer line.
-
-@item niired
-[6584@AA{}] NII doublet's redder line.
-
-@item nii
-@cindex Doublet: NII
-@cindex NII doublet
-[6566@AA{}] NII doublet's mean center.
-
-@item halpha
-@cindex H-alpha
-[6562.8@AA{}] H-@mymath{\alpha} line.
-
-@item niiblue
-[6548@AA{}] NII doublet's bluer line.
-
-@item oiiired-vis
-[5007@AA{}] OIII doublet's redder line in the visible.
-
-@item oiii-vis
-@cindex Doublet: OIII (visible)
-@cindex OIII doublet in visible
-[4983@AA{}] OIII doublet's mean center in the visible.
-
-@item oiiiblue-vis
-[4959@AA{}] OIII doublet's bluer line in the visible.
-
-@item hbeta
-@cindex H-beta
-[4861.36@AA{}] H-@mymath{\beta} line.
-
-@item heii-vis
-[4686@AA{}] HeII doublet's redder line in the visible.
-
-@item hgamma
-@cindex H-gamma
-[4340.46@AA{}] H-@mymath{\gamma} line.
-
-@item hdelta
-@cindex H-delta
-[4101.74@AA{}] H-@mymath{\delta} line.
+For example, @option{--obsline=Ly-alpha,6000} is the same as
@option{--obsline=1215.64,6000}.
+Wavelengths are assumed to be in Angstroms by default (other units can be
selected with @option{--lineunit}, see @ref{CosmicCalculator spectral line
calculations}).
-@item hepsilon
-@cindex H-epsilon
-[3970.07@AA{}] H-@mymath{\epsilon} line.
-
-@item neiii
-[3869@AA{}] NEIII line.
-
-@item oiired
-[3729@AA{}] OII doublet's redder line.
-
-@item oii
-@cindex Doublet: OII
-@cindex OII doublet
-[3727.5@AA{}] OII doublet's mean center.
-
-@item oiiblue
-[3726@AA{}] OII doublet's bluer line.
-
-@item blimit
-@cindex Balmer limit
-[3646@AA{}] Balmer limit.
-
-@item mgiired
-[2803@AA{}] MgII doublet's redder line.
-
-@item mgii
-@cindex Doublet: MgII
-@cindex MgII doublet
-[2799.5@AA{}] MgII doublet's mean center.
-
-@item mgiiblue
-[2796@AA{}] MgII doublet's bluer line.
-
-@item ciiired
-[1909@AA{}] CIII doublet's redder line.
-
-@item ciii
-@cindex Doublet: CIII
-@cindex CIII doublet
-[1908@AA{}] CIII doublet's mean center.
-
-@item ciiiblue
-[1907@AA{}] CIII doublet's bluer line.
-
-@item si_iiired
-[1892@AA{}] SiIII doublet's redder line.
-
-@item si_iii
-@cindex Doublet: SiIII
-@cindex SiIII doublet
-[1887.5@AA{}] SiIII doublet's mean center.
-
-@item si_iiiblue
-[1883@AA{}] SiIII doublet's bluer line.
-
-@item oiiired-uv
-[1666@AA{}] OIII doublet's redder line in the ultra-violet.
-
-@item oiii-uv
-@cindex Doublet: OIII (in UV)
-@cindex OIII doublet in UV
-[1663.5@AA{}] OIII doublet's mean center in the ultra-violet.
-
-@item oiiiblue-uv
-[1661@AA{}] OIII doublet's bluer line in the ultra-violet.
-
-@item heii-uv
-[1640@AA{}] HeII doublet's bluer line in the ultra-violet.
-
-@item civred
-[1551@AA{}] CIV doublet's redder line.
-
-@item civ
-@cindex Doublet: CIV
-@cindex CIV doublet
-[1549@AA{}] CIV doublet's mean center.
-
-@item civblue
-[1548@AA{}] CIV doublet's bluer line.
-
-@item nv
-[1240@AA{}] NV (four times ionized Sodium).
-
-@item lyalpha
-@cindex Lyman-alpha
-[1215.67@AA{}] Lyman-@mymath{\alpha} line.
-
-@item lybeta
-@cindex Lyman-beta
-[1025.7@AA{}] Lyman-@mymath{\beta} line.
-
-@item lygamma
-@cindex Lyman-gamma
-[972.54@AA{}] Lyman-@mymath{\gamma} line.
-
-@item lydelta
-@cindex Lyman-delta
-[949.74@AA{}] Lyman-@mymath{\delta} line.
-
-@item lyepsilon
-@cindex Lyman-epsilon
-[937.80@AA{}] Lyman-@mymath{\epsilon} line.
-
-@item lylimit
-@cindex Lyman limit
-[912@AA{}] Lyman limit.
-
-@end table
+The list of pre-defined names for the lines in Gnuastro's database is
available by running
+@example
+$ astcosmiccal --listlines
+@end example
@end table
@@ -28782,6 +29629,8 @@ Note that @option{--obsline} is an input parameter, so
it is discussed (with the
@item --listlines
List the pre-defined rest frame spectral line wavelengths and their names on
standard output, then abort CosmicCalculator.
+The units of the displayed wavelengths for each line can be determined with
@option{--lineunit} (see below).
+
When this option is given, other operations on the command-line will be
ignored.
This is convenient when you forget the specific name of the spectral line used
within Gnuastro, or when you forget the exact wavelength of a certain line.
@@ -28802,15 +29651,35 @@ And if you want to use the list later and have it as
a table in a file, you can
@item --listlinesatz
Similar to @option{--listlines} (above), but the printed wavelength is not in
the rest frame, but redshifted to the given redshift.
Recall that the redshift can be specified by @option{--redshift} directly or
by @option{--obsline}, see @ref{CosmicCalculator input options}.
+For an example usage of this option, see @ref{Viewing spectra and redshifted
lines}.
@item -i STR/FLT
@itemx --lineatz=STR/FLT
The wavelength of the specified line at the redshift given to CosmicCalculator.
The line can be specified either by its name or directly as a number (its
wavelength).
+The units of the displayed wavelengths for each line can be determined with
@option{--lineunit} (see below).
+
To get the list of pre-defined names for the lines and their wavelength, you
can use the @option{--listlines} option, see @ref{CosmicCalculator input
options}.
In the former case (when a name is given), the returned number is in units of
Angstroms.
In the latter (when a number is given), the returned value is the same units
of the input number (assuming it is a wavelength).
+@item --lineunit=STR
+The units to display line wavelengths above.
+It can take the following four values.
+If you need any other unit, please contact us at @code{bug-gnuastro@@gnu.org}.
+
+@table @code
+@item m
+Meter.
+@item micro-m
+Micrometer or @mymath{10^{-6}m}.
+@item nano-m
+Nanometer, or @mymath{10^{-9}m}.
+@item angstrom
+Angstrom or @mymath{10^{-10}m}; the default unit when this option is not
called.
+@end table
+
+
@end table
@@ -33403,7 +34272,7 @@ However (when necessary) @code{dsize} must not have any
zero values (a dimension
@deftypefun {gal_data_t *} gal_data_alloc_empty (size_t @code{ndim}, size_t
@code{minmapsize}, int @code{quietmmap})
Allocate an empty dataset with a certain number of dimensions, but no 'array'
component.
The @code{size} element will be set to zero and the @code{dsize} array will be
properly allocated (based on the number of dimensions), but all elements will
be zero.
-This is useful in scenarios where you just need a @code{gal_data_t} for meta
data.
+This is useful in scenarios where you just need a @code{gal_data_t} for
metadata.
@end deftypefun
@@ -33908,11 +34777,11 @@ Extract space-separated components of the input
string.
If any space element should be kept (and not considered as a delimiter between
two tokens), precede it with a back-slash (@code{\}).
@end deftypefun
-@deftypefun {char *} gal_list_str_cat (gal_list_str_t @code{*list})
-Concatenate (append) the input list of strings into a single space-separated
string.
+@deftypefun {char *} gal_list_str_cat (gal_list_str_t @code{*list}, char
@code{delimiter})
+Concatenate (append) the input list of strings into a single string where each
node is separated from the next with the given @code{delimiter}.
The space for the output string is allocated by this function and should be
freed when you have finished with it.
-If there is any SPACE characters in any of the elements, a back-slash
(@code{\}) will be printed before the SPACE character.
+If there is any delimiter characters are present in any of the elements, a
back-slash (@code{\}) will be printed before the SPACE character.
This is necessary, otherwise, a function like @code{gal_list_str_extract} will
not be able to extract the elements back into separate elements in a list.
@end deftypefun
@@ -34695,7 +35564,7 @@ use these anywhere you see the @code{tableformat}
variable.
@deffnx Macro GAL_TABLE_SEARCH_COMMENT
When the desired column is not a number, these values determine if the
string to match, or regular expression to search, be in the @emph{name},
-@emph{units} or @emph{comments} of the column meta data. These values
+@emph{units} or @emph{comments} of the column metadata. These values
should be used for the @code{searchin} variables of the functions.
@end deffn
@@ -37990,48 +38859,38 @@ inverse: AFTER[ perm[i] ] = BEFORE[ i ]
i = 0 .. N-1
@end example
@cindex GNU Scientific Library
-The functions here are a re-implementation of the GNU Scientific Library's
-@code{gsl_permute} function. The reason we did not use that function was
-that it uses system-specific types (like @code{long} and @code{int}) which
-can have different widths on different systems, hence are not easily
-convertible to Gnuastro's fixed width types (see @ref{Numeric data
-types}). There is also a separate function for each type, heavily using
-macros to allow a @code{base} function to work on all the types. Thus it is
-hard to read/understand. Hence, Gnuastro contains a re-write of their steps
-in a new type-agnostic method which is a single function that can work on
-any type.
-
-As described in GSL's source code and manual, this implementation comes
-from Donald Knuth's @emph{Art of computer programming} book, in the
-"Sorting and Searching" chapter of Volume 3 (3rd ed). Exercise 10 of
-Section 5.2 defines the problem and in the answers, Knuth describes the
-solution. So if you are interested, please have a look there for more.
-
-We are in contact with the GSL developers and in the
-future@footnote{Gnuastro's @url{http://savannah.gnu.org/task/?14497, Task
-14497}. If this task is still ``postponed'' when you are reading this and
-you are interested to help, your contributions would be very welcome. Both
Gnuastro
-and GSL developers are very busy, hence both would appreciate your help.}
-we will submit these implementations to GSL. If they are finally
-incorporated there, we will delete this section in future versions.
+The functions here are a re-implementation of the GNU Scientific Library's
@code{gsl_permute} function.
+The reason we did not use that function was that it uses system-specific types
(like @code{long} and @code{int}) which can have different widths on different
systems, hence are not easily convertible to Gnuastro's fixed width types (see
@ref{Numeric data types}).
+There is also a separate function for each type, heavily using macros to allow
a @code{base} function to work on all the types.
+Thus it is hard to read/understand.
+Hence, Gnuastro contains a re-write of their steps in a new type-agnostic
method which is a single function that can work on any type.
+
+As described in GSL's source code and manual, this implementation comes from
Donald Knuth's @emph{Art of computer programming} book, in the "Sorting and
Searching" chapter of Volume 3 (3rd ed).
+Exercise 10 of Section 5.2 defines the problem and in the answers, Knuth
describes the solution.
+So if you are interested, please have a look there for more.
+
+We are in contact with the GSL developers and in the
future@footnote{Gnuastro's @url{http://savannah.gnu.org/task/?14497, Task
14497}.
+If this task is still ``postponed'' when you are reading this and you are
interested to help, your contributions would be very welcome.
+Both Gnuastro and GSL developers are very busy, hence both would appreciate
your help.} we will submit these implementations to GSL.
+If they are finally incorporated there, we will delete this section in future
versions.
@deftypefun void gal_permutation_check (size_t @code{*permutation}, size_t
@code{size})
-Print how @code{permutation} will re-order an array that has @code{size}
-elements for each element in one one line.
+Print how @code{permutation} will re-order an array that has @code{size}
elements for each element in one one line.
@end deftypefun
@deftypefun void gal_permutation_apply (gal_data_t @code{*input}, size_t
@code{*permutation})
-Apply @code{permutation} on the @code{input} dataset (can have any type),
-see above for the definition of permutation.
+Apply @code{permutation} on the @code{input} dataset (can have any type), see
above for the definition of permutation.
@end deftypefun
@deftypefun void gal_permutation_apply_inverse (gal_data_t @code{*input},
size_t @code{*permutation})
-Apply the inverse of @code{permutation} on the @code{input} dataset (can
-have any type), see above for the definition of permutation.
+Apply the inverse of @code{permutation} on the @code{input} dataset (can have
any type), see above for the definition of permutation.
@end deftypefun
-
-
+@deftypefun void gal_permutation_transpose_2d (gal_data_t @code{*input})
+Transpose an input 2D matrix into a new dataset.
+If the input is not a square, this function will change the
@code{input->array} element to a newly allocated array (the old one will be
freed internally).
+Therefore, in case you have already stored @code{input->array} for other usage
@emph{before} this function, and the input is not a square, be sure to update
the previously stored pointer if the input is not a square.
+@end deftypefun
@node Matching, Statistical operations, Permutations, Gnuastro library
@@ -38080,7 +38939,8 @@ If @code{aperture[1]==1}, the aperture will be a circle
of radius @code{aperture
When the aperture is an ellipse, distances between the points are also
calculated in the respective elliptical distances (@mymath{r_{el}} in
@ref{Defining an ellipse and ellipsoid}).
@strong{Output permutations ignore internal sorting}: the output permutations
will correspond to the initial inputs.
-Therefore, even when @code{inplace!=0} (and this function re-arranges the
inputs in place), the output permutation will correspond to original (possibly
non-sorted) inputs. The reason for this is that you rarely want to permute the
actual positional columns after the match.
+Therefore, even when @code{inplace!=0} (and this function re-arranges the
inputs in place), the output permutation will correspond to original (possibly
non-sorted) inputs.
+The reason for this is that you rarely want to permute the actual positional
columns after the match.
Usually, you also have other columns (such as the magnitude and morphology)
and you want to find how they differ between the objects that match.
Once you have the permutations, they can be applied to those other columns
(see @ref{Permutations}) and the higher-level processing can continue.
So if you do not need the coordinate columns for the rest of your analysis, it
is better to set @code{inplace=1}.
@@ -39939,40 +40799,246 @@ All these functions are declared in
@file{gnuastro/spectra.h}.
@cindex Doublet: MgII
@cindex Doublet: CIII
@deffn Macro GAL_SPECLINES_INVALID
-@deffnx Macro GAL_SPECLINES_SIIRED
-@deffnx Macro GAL_SPECLINES_SII
-@deffnx Macro GAL_SPECLINES_SIIBLUE
-@deffnx Macro GAL_SPECLINES_NIIRED
-@deffnx Macro GAL_SPECLINES_NII
-@deffnx Macro GAL_SPECLINES_HALPHA
-@deffnx Macro GAL_SPECLINES_NIIBLUE
-@deffnx Macro GAL_SPECLINES_OIIIRED
-@deffnx Macro GAL_SPECLINES_OIII
-@deffnx Macro GAL_SPECLINES_OIIIBLUE
-@deffnx Macro GAL_SPECLINES_HBETA
-@deffnx Macro GAL_SPECLINES_HEIIRED
-@deffnx Macro GAL_SPECLINES_HGAMMA
-@deffnx Macro GAL_SPECLINES_HDELTA
-@deffnx Macro GAL_SPECLINES_HEPSILON
-@deffnx Macro GAL_SPECLINES_NEIII
-@deffnx Macro GAL_SPECLINES_OIIRED
-@deffnx Macro GAL_SPECLINES_OII
-@deffnx Macro GAL_SPECLINES_OIIBLUE
-@deffnx Macro GAL_SPECLINES_BLIMIT
-@deffnx Macro GAL_SPECLINES_MGIIRED
-@deffnx Macro GAL_SPECLINES_MGII
-@deffnx Macro GAL_SPECLINES_MGIIBLUE
-@deffnx Macro GAL_SPECLINES_CIIIRED
-@deffnx Macro GAL_SPECLINES_CIII
-@deffnx Macro GAL_SPECLINES_CIIIBLUE
-@deffnx Macro GAL_SPECLINES_HEIIBLUE
-@deffnx Macro GAL_SPECLINES_LYALPHA
-@deffnx Macro GAL_SPECLINES_LYLIMIT
-@deffnx Macro GAL_SPECLINES_INVALID_MAX
-Internal values/identifiers for specific spectral lines as is clear from
-their names.
-Note the first and last one, they can be used when parsing the lines
automatically: both do not correspond to any line, but their integer values
correspond to the two integers just before and after the first and last line
identifier.
-
+@deffnx Macro GAL_SPECLINES_Ne_VIII_770
+@deffnx Macro GAL_SPECLINES_Ne_VIII_780
+@deffnx Macro GAL_SPECLINES_Ly_epsilon
+@deffnx Macro GAL_SPECLINES_Ly_delta
+@deffnx Macro GAL_SPECLINES_Ly_gamma
+@deffnx Macro GAL_SPECLINES_C_III_977
+@deffnx Macro GAL_SPECLINES_N_III_989
+@deffnx Macro GAL_SPECLINES_N_III_991_51
+@deffnx Macro GAL_SPECLINES_N_III_991_57
+@deffnx Macro GAL_SPECLINES_Ly_beta
+@deffnx Macro GAL_SPECLINES_O_VI_1031
+@deffnx Macro GAL_SPECLINES_O_VI_1037
+@deffnx Macro GAL_SPECLINES_Ar_I_1066
+@deffnx Macro GAL_SPECLINES_Ly_alpha
+@deffnx Macro GAL_SPECLINES_N_V_1238
+@deffnx Macro GAL_SPECLINES_N_V_1242
+@deffnx Macro GAL_SPECLINES_Si_II_1260
+@deffnx Macro GAL_SPECLINES_Si_II_1264
+@deffnx Macro GAL_SPECLINES_O_I_1302
+@deffnx Macro GAL_SPECLINES_C_II_1334
+@deffnx Macro GAL_SPECLINES_C_II_1335
+@deffnx Macro GAL_SPECLINES_Si_IV_1393
+@deffnx Macro GAL_SPECLINES_O_IV_1397
+@deffnx Macro GAL_SPECLINES_O_IV_1399
+@deffnx Macro GAL_SPECLINES_Si_IV_1402
+@deffnx Macro GAL_SPECLINES_N_IV_1486
+@deffnx Macro GAL_SPECLINES_C_IV_1548
+@deffnx Macro GAL_SPECLINES_C_IV_1550
+@deffnx Macro GAL_SPECLINES_He_II_1640
+@deffnx Macro GAL_SPECLINES_O_III_1660
+@deffnx Macro GAL_SPECLINES_O_III_1666
+@deffnx Macro GAL_SPECLINES_N_III_1746
+@deffnx Macro GAL_SPECLINES_N_III_1748
+@deffnx Macro GAL_SPECLINES_Al_III_1854
+@deffnx Macro GAL_SPECLINES_Al_III_1862
+@deffnx Macro GAL_SPECLINES_Si_III
+@deffnx Macro GAL_SPECLINES_C_III_1908
+@deffnx Macro GAL_SPECLINES_N_II_2142
+@deffnx Macro GAL_SPECLINES_O_III_2320
+@deffnx Macro GAL_SPECLINES_C_II_2323
+@deffnx Macro GAL_SPECLINES_C_II_2324
+@deffnx Macro GAL_SPECLINES_Fe_XI_2648
+@deffnx Macro GAL_SPECLINES_He_II_2733
+@deffnx Macro GAL_SPECLINES_Mg_V_2782
+@deffnx Macro GAL_SPECLINES_Mg_II_2795
+@deffnx Macro GAL_SPECLINES_Mg_II_2802
+@deffnx Macro GAL_SPECLINES_Fe_IV_2829
+@deffnx Macro GAL_SPECLINES_Fe_IV_2835
+@deffnx Macro GAL_SPECLINES_Ar_IV_2853
+@deffnx Macro GAL_SPECLINES_Ar_IV_2868
+@deffnx Macro GAL_SPECLINES_Mg_V_2928
+@deffnx Macro GAL_SPECLINES_He_I_2945
+@deffnx Macro GAL_SPECLINES_O_III_3132
+@deffnx Macro GAL_SPECLINES_He_I_3187
+@deffnx Macro GAL_SPECLINES_He_II_3203
+@deffnx Macro GAL_SPECLINES_O_III_3312
+@deffnx Macro GAL_SPECLINES_Ne_V_3345
+@deffnx Macro GAL_SPECLINES_Ne_V_3425
+@deffnx Macro GAL_SPECLINES_O_III_3444
+@deffnx Macro GAL_SPECLINES_N_I_3466_4
+@deffnx Macro GAL_SPECLINES_N_I_3466_5
+@deffnx Macro GAL_SPECLINES_He_I_3487
+@deffnx Macro GAL_SPECLINES_Fe_VII_3586
+@deffnx Macro GAL_SPECLINES_Fe_VI_3662
+@deffnx Macro GAL_SPECLINES_H_19
+@deffnx Macro GAL_SPECLINES_H_18
+@deffnx Macro GAL_SPECLINES_H_17
+@deffnx Macro GAL_SPECLINES_H_16
+@deffnx Macro GAL_SPECLINES_H_15
+@deffnx Macro GAL_SPECLINES_H_14
+@deffnx Macro GAL_SPECLINES_O_II_3726
+@deffnx Macro GAL_SPECLINES_O_II_3728
+@deffnx Macro GAL_SPECLINES_H_13
+@deffnx Macro GAL_SPECLINES_H_12
+@deffnx Macro GAL_SPECLINES_Fe_VII_3758
+@deffnx Macro GAL_SPECLINES_H_11
+@deffnx Macro GAL_SPECLINES_H_10
+@deffnx Macro GAL_SPECLINES_H_9
+@deffnx Macro GAL_SPECLINES_Fe_V_3839
+@deffnx Macro GAL_SPECLINES_Ne_III_3868
+@deffnx Macro GAL_SPECLINES_He_I_3888
+@deffnx Macro GAL_SPECLINES_H_8
+@deffnx Macro GAL_SPECLINES_Fe_V_3891
+@deffnx Macro GAL_SPECLINES_Fe_V_3911
+@deffnx Macro GAL_SPECLINES_Ne_III_3967
+@deffnx Macro GAL_SPECLINES_H_epsilon
+@deffnx Macro GAL_SPECLINES_He_I_4026
+@deffnx Macro GAL_SPECLINES_S_II_4068
+@deffnx Macro GAL_SPECLINES_Fe_V_4071
+@deffnx Macro GAL_SPECLINES_S_II_4076
+@deffnx Macro GAL_SPECLINES_H_delta
+@deffnx Macro GAL_SPECLINES_He_I_4143
+@deffnx Macro GAL_SPECLINES_Fe_II_4178
+@deffnx Macro GAL_SPECLINES_Fe_V_4180
+@deffnx Macro GAL_SPECLINES_Fe_II_4233
+@deffnx Macro GAL_SPECLINES_Fe_V_4227
+@deffnx Macro GAL_SPECLINES_Fe_II_4287
+@deffnx Macro GAL_SPECLINES_Fe_II_4304
+@deffnx Macro GAL_SPECLINES_O_II_4317
+@deffnx Macro GAL_SPECLINES_H_gamma
+@deffnx Macro GAL_SPECLINES_O_III_4363
+@deffnx Macro GAL_SPECLINES_Ar_XIV
+@deffnx Macro GAL_SPECLINES_O_II_4414
+@deffnx Macro GAL_SPECLINES_Fe_II_4416
+@deffnx Macro GAL_SPECLINES_Fe_II_4452
+@deffnx Macro GAL_SPECLINES_He_I_4471
+@deffnx Macro GAL_SPECLINES_Fe_II_4489
+@deffnx Macro GAL_SPECLINES_Fe_II_4491
+@deffnx Macro GAL_SPECLINES_N_III_4510
+@deffnx Macro GAL_SPECLINES_Fe_II_4522
+@deffnx Macro GAL_SPECLINES_Fe_II_4555
+@deffnx Macro GAL_SPECLINES_Fe_II_4582
+@deffnx Macro GAL_SPECLINES_Fe_II_4583
+@deffnx Macro GAL_SPECLINES_Fe_II_4629
+@deffnx Macro GAL_SPECLINES_N_III_4634
+@deffnx Macro GAL_SPECLINES_N_III_4640
+@deffnx Macro GAL_SPECLINES_N_III_4641
+@deffnx Macro GAL_SPECLINES_C_III_4647
+@deffnx Macro GAL_SPECLINES_C_III_4650
+@deffnx Macro GAL_SPECLINES_C_III_5651
+@deffnx Macro GAL_SPECLINES_Fe_III_4658
+@deffnx Macro GAL_SPECLINES_He_II_4685
+@deffnx Macro GAL_SPECLINES_Ar_IV_4711
+@deffnx Macro GAL_SPECLINES_Ar_IV_4740
+@deffnx Macro GAL_SPECLINES_H_beta
+@deffnx Macro GAL_SPECLINES_Fe_VII_4893
+@deffnx Macro GAL_SPECLINES_Fe_IV_4903
+@deffnx Macro GAL_SPECLINES_Fe_II_4923
+@deffnx Macro GAL_SPECLINES_O_III_4958
+@deffnx Macro GAL_SPECLINES_O_III_5006
+@deffnx Macro GAL_SPECLINES_Fe_II_5018
+@deffnx Macro GAL_SPECLINES_Fe_III_5084
+@deffnx Macro GAL_SPECLINES_Fe_VI_5145
+@deffnx Macro GAL_SPECLINES_Fe_VII_5158
+@deffnx Macro GAL_SPECLINES_Fe_II_5169
+@deffnx Macro GAL_SPECLINES_Fe_VI_5176
+@deffnx Macro GAL_SPECLINES_Fe_II_5197
+@deffnx Macro GAL_SPECLINES_N_I_5200
+@deffnx Macro GAL_SPECLINES_Fe_II_5234
+@deffnx Macro GAL_SPECLINES_Fe_IV_5236
+@deffnx Macro GAL_SPECLINES_Fe_III_5270
+@deffnx Macro GAL_SPECLINES_Fe_II_5276
+@deffnx Macro GAL_SPECLINES_Fe_VII_5276
+@deffnx Macro GAL_SPECLINES_Fe_XIV
+@deffnx Macro GAL_SPECLINES_Ca_V
+@deffnx Macro GAL_SPECLINES_Fe_II_5316_6
+@deffnx Macro GAL_SPECLINES_Fe_II_5316_7
+@deffnx Macro GAL_SPECLINES_Fe_VI_5335
+@deffnx Macro GAL_SPECLINES_Fe_VI_5424
+@deffnx Macro GAL_SPECLINES_Cl_III_5517
+@deffnx Macro GAL_SPECLINES_Cl_III_5537
+@deffnx Macro GAL_SPECLINES_Fe_VI_5637
+@deffnx Macro GAL_SPECLINES_Fe_VI_5677
+@deffnx Macro GAL_SPECLINES_C_III_5697
+@deffnx Macro GAL_SPECLINES_Fe_VII_5720
+@deffnx Macro GAL_SPECLINES_N_II_5754
+@deffnx Macro GAL_SPECLINES_C_IV_5801
+@deffnx Macro GAL_SPECLINES_C_IV_5811
+@deffnx Macro GAL_SPECLINES_He_I_5875
+@deffnx Macro GAL_SPECLINES_O_I_6046
+@deffnx Macro GAL_SPECLINES_Fe_VII_6087
+@deffnx Macro GAL_SPECLINES_O_I_6300
+@deffnx Macro GAL_SPECLINES_S_III_6312
+@deffnx Macro GAL_SPECLINES_Si_II_6347
+@deffnx Macro GAL_SPECLINES_O_I_6363
+@deffnx Macro GAL_SPECLINES_Fe_II_6369
+@deffnx Macro GAL_SPECLINES_Fe_X
+@deffnx Macro GAL_SPECLINES_Fe_II_6516
+@deffnx Macro GAL_SPECLINES_N_II_6548
+@deffnx Macro GAL_SPECLINES_H_alpha
+@deffnx Macro GAL_SPECLINES_N_II_6583
+@deffnx Macro GAL_SPECLINES_S_II_6716
+@deffnx Macro GAL_SPECLINES_S_II_6730
+@deffnx Macro GAL_SPECLINES_O_I_7002
+@deffnx Macro GAL_SPECLINES_Ar_V
+@deffnx Macro GAL_SPECLINES_He_I_7065
+@deffnx Macro GAL_SPECLINES_Ar_III_7135
+@deffnx Macro GAL_SPECLINES_Fe_II_7155
+@deffnx Macro GAL_SPECLINES_Ar_IV_7170
+@deffnx Macro GAL_SPECLINES_Fe_II_7172
+@deffnx Macro GAL_SPECLINES_C_II_7236
+@deffnx Macro GAL_SPECLINES_Ar_IV_7237
+@deffnx Macro GAL_SPECLINES_O_I_7254
+@deffnx Macro GAL_SPECLINES_Ar_IV_7262
+@deffnx Macro GAL_SPECLINES_He_I_7281
+@deffnx Macro GAL_SPECLINES_O_II_7319
+@deffnx Macro GAL_SPECLINES_O_II_7330
+@deffnx Macro GAL_SPECLINES_Ni_II_7377
+@deffnx Macro GAL_SPECLINES_Ni_II_7411
+@deffnx Macro GAL_SPECLINES_Fe_II_7452
+@deffnx Macro GAL_SPECLINES_N_I_7468
+@deffnx Macro GAL_SPECLINES_S_XII
+@deffnx Macro GAL_SPECLINES_Ar_III_7751
+@deffnx Macro GAL_SPECLINES_He_I_7816
+@deffnx Macro GAL_SPECLINES_Ar_I_7868
+@deffnx Macro GAL_SPECLINES_Ni_III
+@deffnx Macro GAL_SPECLINES_Fe_XI_7891
+@deffnx Macro GAL_SPECLINES_He_II_8236
+@deffnx Macro GAL_SPECLINES_Pa_20
+@deffnx Macro GAL_SPECLINES_Pa_19
+@deffnx Macro GAL_SPECLINES_Pa_18
+@deffnx Macro GAL_SPECLINES_O_I_8446
+@deffnx Macro GAL_SPECLINES_Pa_17
+@deffnx Macro GAL_SPECLINES_Ca_II_8498
+@deffnx Macro GAL_SPECLINES_Pa_16
+@deffnx Macro GAL_SPECLINES_Ca_II_8542
+@deffnx Macro GAL_SPECLINES_Pa_15
+@deffnx Macro GAL_SPECLINES_Cl_II
+@deffnx Macro GAL_SPECLINES_Pa_14
+@deffnx Macro GAL_SPECLINES_Fe_II_8616
+@deffnx Macro GAL_SPECLINES_Ca_II_8662
+@deffnx Macro GAL_SPECLINES_Pa_13
+@deffnx Macro GAL_SPECLINES_N_I_8680
+@deffnx Macro GAL_SPECLINES_N_I_8703
+@deffnx Macro GAL_SPECLINES_N_I_8711
+@deffnx Macro GAL_SPECLINES_Pa_12
+@deffnx Macro GAL_SPECLINES_Pa_11
+@deffnx Macro GAL_SPECLINES_Fe_II_8891
+@deffnx Macro GAL_SPECLINES_Pa_10
+@deffnx Macro GAL_SPECLINES_S_III_9068
+@deffnx Macro GAL_SPECLINES_Pa_9
+@deffnx Macro GAL_SPECLINES_S_III_9531
+@deffnx Macro GAL_SPECLINES_Pa_epsilon
+@deffnx Macro GAL_SPECLINES_C_I_9824
+@deffnx Macro GAL_SPECLINES_C_I_9850
+@deffnx Macro GAL_SPECLINES_S_VIII
+@deffnx Macro GAL_SPECLINES_He_I_10027
+@deffnx Macro GAL_SPECLINES_He_I_10031
+@deffnx Macro GAL_SPECLINES_Pa_delta
+@deffnx Macro GAL_SPECLINES_S_II_10286
+@deffnx Macro GAL_SPECLINES_S_II_10320
+@deffnx Macro GAL_SPECLINES_S_II_10336
+@deffnx Macro GAL_SPECLINES_Fe_XIII
+@deffnx Macro GAL_SPECLINES_He_I_10830
+@deffnx Macro GAL_SPECLINES_Pa_gamma
+@deffnx Macro GAL_SPECLINES_NUMBER
+Internal values/identifiers for recognized spectral lines as is clear from
their names.
+They are based on the UV an optical table of galaxy emission lines of Drew
Chojnowski@footnote{@url{http://astronomy.nmsu.edu/drewski/tableofemissionlines.html}}.
+
+Note the first and last macros, they can be used when parsing the lines
automatically: both do not correspond to any line, but their integer values
correspond to the two integers just before and after the first and last line
identifier:
@code{GAL_SPECLINES_INVALID} has a value of zero, and allows you to have a
fixed integer which never corresponds to a line.
@code{GAL_SPECLINES_INVALID_MAX} is the total number of pre-defined lines,
plus one.
So you can parse all the known lines with a @code{for} loop like this:
@@ -39981,70 +41047,14 @@ for(i=1;i<GAL_SPECLINES_INVALID_MAX;++i)
@end example
@end deffn
-@deffn Macro GAL_SPECLINES_ANGSTROM_SIIRED
-@deffnx Macro GAL_SPECLINES_ANGSTROM_SII
-@deffnx Macro GAL_SPECLINES_ANGSTROM_SIIBLUE
-@deffnx Macro GAL_SPECLINES_ANGSTROM_NIIRED
-@deffnx Macro GAL_SPECLINES_ANGSTROM_NII
-@deffnx Macro GAL_SPECLINES_ANGSTROM_HALPHA
-@deffnx Macro GAL_SPECLINES_ANGSTROM_NIIBLUE
-@deffnx Macro GAL_SPECLINES_ANGSTROM_OIIIRED
-@deffnx Macro GAL_SPECLINES_ANGSTROM_OIII
-@deffnx Macro GAL_SPECLINES_ANGSTROM_OIIIBLUE
-@deffnx Macro GAL_SPECLINES_ANGSTROM_HBETA
-@deffnx Macro GAL_SPECLINES_ANGSTROM_HEIIRED
-@deffnx Macro GAL_SPECLINES_ANGSTROM_HGAMMA
-@deffnx Macro GAL_SPECLINES_ANGSTROM_HDELTA
-@deffnx Macro GAL_SPECLINES_ANGSTROM_HEPSILON
-@deffnx Macro GAL_SPECLINES_ANGSTROM_NEIII
-@deffnx Macro GAL_SPECLINES_ANGSTROM_OIIRED
-@deffnx Macro GAL_SPECLINES_ANGSTROM_OII
-@deffnx Macro GAL_SPECLINES_ANGSTROM_OIIBLUE
-@deffnx Macro GAL_SPECLINES_ANGSTROM_BLIMIT
-@deffnx Macro GAL_SPECLINES_ANGSTROM_MGIIRED
-@deffnx Macro GAL_SPECLINES_ANGSTROM_MGII
-@deffnx Macro GAL_SPECLINES_ANGSTROM_MGIIBLUE
-@deffnx Macro GAL_SPECLINES_ANGSTROM_CIIIRED
-@deffnx Macro GAL_SPECLINES_ANGSTROM_CIII
-@deffnx Macro GAL_SPECLINES_ANGSTROM_CIIIBLUE
-@deffnx Macro GAL_SPECLINES_ANGSTROM_HEIIBLUE
-@deffnx Macro GAL_SPECLINES_ANGSTROM_LYALPHA
-@deffnx Macro GAL_SPECLINES_ANGSTROM_LYLIMIT
+@deffn Macro GAL_SPECLINES_ANGSTROM_*
Wavelength (in Angstroms) of the named lines.
+The @code{*} can take any of the line names of the @code{GAL_SPECLINES_*}
Macros above.
@end deffn
-@deffn Macro GAL_SPECLINES_NAME_SIIRED
-@deffnx Macro GAL_SPECLINES_NAME_SII
-@deffnx Macro GAL_SPECLINES_NAME_SIIBLUE
-@deffnx Macro GAL_SPECLINES_NAME_NIIRED
-@deffnx Macro GAL_SPECLINES_NAME_NII
-@deffnx Macro GAL_SPECLINES_NAME_HALPHA
-@deffnx Macro GAL_SPECLINES_NAME_NIIBLUE
-@deffnx Macro GAL_SPECLINES_NAME_OIIIRED
-@deffnx Macro GAL_SPECLINES_NAME_OIII
-@deffnx Macro GAL_SPECLINES_NAME_OIIIBLUE
-@deffnx Macro GAL_SPECLINES_NAME_HBETA
-@deffnx Macro GAL_SPECLINES_NAME_HEIIRED
-@deffnx Macro GAL_SPECLINES_NAME_HGAMMA
-@deffnx Macro GAL_SPECLINES_NAME_HDELTA
-@deffnx Macro GAL_SPECLINES_NAME_HEPSILON
-@deffnx Macro GAL_SPECLINES_NAME_NEIII
-@deffnx Macro GAL_SPECLINES_NAME_OIIRED
-@deffnx Macro GAL_SPECLINES_NAME_OII
-@deffnx Macro GAL_SPECLINES_NAME_OIIBLUE
-@deffnx Macro GAL_SPECLINES_NAME_BLIMIT
-@deffnx Macro GAL_SPECLINES_NAME_MGIIRED
-@deffnx Macro GAL_SPECLINES_NAME_MGII
-@deffnx Macro GAL_SPECLINES_NAME_MGIIBLUE
-@deffnx Macro GAL_SPECLINES_NAME_CIIIRED
-@deffnx Macro GAL_SPECLINES_NAME_CIII
-@deffnx Macro GAL_SPECLINES_NAME_CIIIBLUE
-@deffnx Macro GAL_SPECLINES_NAME_HEIIBLUE
-@deffnx Macro GAL_SPECLINES_NAME_LYALPHA
-@deffnx Macro GAL_SPECLINES_NAME_LYLIMIT
-Names (as literal stings without any space, all in small-caps) that can be
-used to refer to the lines in your program and converted to and from line
-identifiers using the functions below.
+@deffn Macro GAL_SPECLINES_NAME_*
+Names (as literal stings without any space) that can be used to refer to the
lines in your program and converted to and from line identifiers using the
functions below.
+The @code{*} can take any of the line names of the @code{GAL_SPECLINES_*}
Macros above.
@end deffn
@deftypefun {char *} gal_speclines_line_name (int @code{linecode})
@@ -40068,9 +41078,12 @@ emitted from (if its restframe wavelength was
@code{restline}).
@end deftypefun
@deftypefun double gal_speclines_line_redshift_code (double @code{obsline},
int @code{linecode})
-Return the redshift where the observed wavelength (@code{obsline}) was
-emitted from (assuming its a specific spectra line, identified with
-@code{linecode}).
+Return the redshift where the observed wavelength (@code{obsline}) was emitted
from a pre-defined spectral line in the macros above.
+For example, you want the redshift where the H-alpha line falls at a
wavelength of 8000 Angsroms, you can call this function like this:
+
+@example
+gal_speclines_line_redshift_code(8000, GAL_SPECLINES_H_alpha);
+@end example
@end deftypefun
diff --git a/lib/fits.c b/lib/fits.c
index 58e0aff8..db74727d 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -3979,23 +3979,24 @@ fits_table_prepare_arrays(gal_data_t *cols, size_t
numcols,
else
{
/* For vector columns, we need to give the number of elements
- in the vector. */
- switch(col->ndim)
+ in the vector. Note that a vector column with dsize[1]==1
+ is just a single-valued column and shouldn't be treated
+ like a vector.*/
+ if( col->ndim==1 || (col->ndim==2 && col->dsize[1]==1) )
{
- case 1:
if( asprintf(&tform[i], "%c", fmt[0])<0 )
error(EXIT_FAILURE, 0, "%s: asprintf allocation",
__func__);
- break;
- case 2:
+ }
+ else if(col->ndim==2) /* Vector column */
+ {
if(asprintf(&tform[i], "%zu%c", col->dsize[1], fmt[0])<0)
error(EXIT_FAILURE, 0, "%s: asprintf allocation",
__func__);
- break;
- default:
- error(EXIT_FAILURE, 0, "%s: only 1D or 2D data can "
- "be written as a binary table", __func__);
}
+ else
+ error(EXIT_FAILURE, 0, "%s: only 1D or 2D data can "
+ "be written as a binary table", __func__);
}
break;
@@ -4215,8 +4216,10 @@ fits_tab_write_col(fitsfile *fptr, gal_data_t *col, int
tableformat,
/* If this is a FITS ASCII table, and the column is vector, we need to
write it as separate single-value columns and write those, then we can
- safely return (no more need to continue). */
- if(tableformat==GAL_TABLE_FORMAT_AFITS && col->ndim>1)
+ safely return (no more need to continue). It may happen that a 2D
+ column has a second dimension of 1! In this case, it should be saved
+ as a normal 1D column. */
+ if(tableformat==GAL_TABLE_FORMAT_AFITS && col->ndim==2 && col->dsize[1]>1)
{
*colind=fits_tab_write_colvec_ascii(fptr, col, *colind, tform,
filename);
diff --git a/lib/gnuastro-internal/options.h b/lib/gnuastro-internal/options.h
index 0ccea4bb..794d32eb 100644
--- a/lib/gnuastro-internal/options.h
+++ b/lib/gnuastro-internal/options.h
@@ -301,9 +301,18 @@ gal_data_t *
gal_options_parse_list_of_numbers(char *string, char *filename,
size_t lineno, uint8_t type);
+gal_list_str_t *
+gal_options_parse_csv_strings_to_list(char *string, char *filename,
+ size_t lineno);
+
gal_data_t *
-gal_options_parse_csv_strings_raw(char *string, char *filename,
- size_t lineno);
+gal_options_parse_csv_strings_to_data(char *string, char *filename,
+ size_t lineno);
+
+void *
+gal_options_parse_csv_strings_append(struct argp_option *option, char *arg,
+ char *filename, size_t lineno,
+ void *junk);
void *
gal_options_parse_csv_strings(struct argp_option *option, char *arg,
diff --git a/lib/gnuastro/list.h b/lib/gnuastro/list.h
index 441ed419..fdb874dc 100644
--- a/lib/gnuastro/list.h
+++ b/lib/gnuastro/list.h
@@ -84,7 +84,7 @@ gal_list_str_t *
gal_list_str_extract(char *string);
char *
-gal_list_str_cat(gal_list_str_t *list);
+gal_list_str_cat(gal_list_str_t *list, char delimiter);
diff --git a/lib/gnuastro/permutation.h b/lib/gnuastro/permutation.h
index f0555b9a..2237ffac 100644
--- a/lib/gnuastro/permutation.h
+++ b/lib/gnuastro/permutation.h
@@ -67,7 +67,8 @@ gal_permutation_apply_onlydim0(gal_data_t *input, size_t
*permutation);
void
gal_permutation_apply_inverse(gal_data_t *input, size_t *permutation);
-
+void
+gal_permutation_transpose_2d(gal_data_t *input);
__END_C_DECLS /* From C++ preparations */
diff --git a/lib/gnuastro/speclines.h b/lib/gnuastro/speclines.h
index f09bc4b6..85c9ac2d 100644
--- a/lib/gnuastro/speclines.h
+++ b/lib/gnuastro/speclines.h
@@ -46,158 +46,776 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
__BEGIN_C_DECLS /* From C++ preparations */
-/* Spectral line internal codes (SORT BY WAVELENGTH). */
+/* Spectral line internal codes (SORT BY WAVELENGTH).
+ rb: right bracket
+ lb: left bracket
+ rlb: left & right bracket
+
+ From: http://astronomy.nmsu.edu/drewski/tableofemissionlines.html
+ Added: Lyman-Gamma from Wikipeda
+*/
enum gal_speclines_line_codes
{
/* Allowing '0' to be identied as a known-non-line. */
GAL_SPECLINES_INVALID=0,
- /* Main list of recognized lines. */
- GAL_SPECLINES_SIIRED,
- GAL_SPECLINES_SII,
- GAL_SPECLINES_SIIBLUE,
- GAL_SPECLINES_NIIRED,
- GAL_SPECLINES_NII,
- GAL_SPECLINES_HALPHA,
- GAL_SPECLINES_NIIBLUE,
- GAL_SPECLINES_OIIIRED_VIS,
- GAL_SPECLINES_OIII_VIS,
- GAL_SPECLINES_OIIIBLUE_VIS,
- GAL_SPECLINES_HBETA,
- GAL_SPECLINES_HEII_VIS,
- GAL_SPECLINES_HGAMMA,
- GAL_SPECLINES_HDELTA,
- GAL_SPECLINES_HEPSILON,
- GAL_SPECLINES_NEIII,
- GAL_SPECLINES_OIIRED,
- GAL_SPECLINES_OII,
- GAL_SPECLINES_OIIBLUE,
- GAL_SPECLINES_BLIMIT,
- GAL_SPECLINES_MGIIRED,
- GAL_SPECLINES_MGII,
- GAL_SPECLINES_MGIIBLUE,
- GAL_SPECLINES_CIIIRED,
- GAL_SPECLINES_CIII,
- GAL_SPECLINES_CIIIBLUE,
- GAL_SPECLINES_SiIIIRED,
- GAL_SPECLINES_SiIII,
- GAL_SPECLINES_SiIIIBLUE,
- GAL_SPECLINES_OIIIRED_UV,
- GAL_SPECLINES_OIII_UV,
- GAL_SPECLINES_OIIIBLUE_UV,
- GAL_SPECLINES_HEII_UV,
- GAL_SPECLINES_CIVRED,
- GAL_SPECLINES_CIV,
- GAL_SPECLINES_CIVBLUE,
- GAL_SPECLINES_NV,
- GAL_SPECLINES_LYALPHA,
- GAL_SPECLINES_LYBETA,
- GAL_SPECLINES_LYGAMMA,
- GAL_SPECLINES_LYDELTA,
- GAL_SPECLINES_LYEPSILON,
- GAL_SPECLINES_LYLIMIT,
+ /* Spectral line names from blue to red. */
+ GAL_SPECLINES_Ne_VIII_770,
+ GAL_SPECLINES_Ne_VIII_780,
+ GAL_SPECLINES_Ly_epsilon,
+ GAL_SPECLINES_Ly_delta,
+ GAL_SPECLINES_Ly_gamma,
+ GAL_SPECLINES_C_III_977,
+ GAL_SPECLINES_N_III_989,
+ GAL_SPECLINES_N_III_991_51,
+ GAL_SPECLINES_N_III_991_57,
+ GAL_SPECLINES_Ly_beta,
+ GAL_SPECLINES_O_VI_1031,
+ GAL_SPECLINES_O_VI_1037,
+ GAL_SPECLINES_Ar_I_1066,
+ GAL_SPECLINES_Ly_alpha,
+ GAL_SPECLINES_N_V_1238,
+ GAL_SPECLINES_N_V_1242,
+ GAL_SPECLINES_Si_II_1260,
+ GAL_SPECLINES_Si_II_1264,
+ GAL_SPECLINES_O_I_1302,
+ GAL_SPECLINES_C_II_1334,
+ GAL_SPECLINES_C_II_1335,
+ GAL_SPECLINES_Si_IV_1393,
+ GAL_SPECLINES_O_IV_1397,
+ GAL_SPECLINES_O_IV_1399,
+ GAL_SPECLINES_Si_IV_1402,
+ GAL_SPECLINES_N_IV_1486,
+ GAL_SPECLINES_C_IV_1548,
+ GAL_SPECLINES_C_IV_1550,
+ GAL_SPECLINES_He_II_1640,
+ GAL_SPECLINES_O_III_1660,
+ GAL_SPECLINES_O_III_1666,
+ GAL_SPECLINES_N_III_1746,
+ GAL_SPECLINES_N_III_1748,
+ GAL_SPECLINES_Al_III_1854,
+ GAL_SPECLINES_Al_III_1862,
+ GAL_SPECLINES_Si_III,
+ GAL_SPECLINES_C_III_1908,
+ GAL_SPECLINES_N_II_2142,
+ GAL_SPECLINES_O_III_2320,
+ GAL_SPECLINES_C_II_2323,
+ GAL_SPECLINES_C_II_2324,
+ GAL_SPECLINES_Fe_XI_2648,
+ GAL_SPECLINES_He_II_2733,
+ GAL_SPECLINES_Mg_V_2782,
+ GAL_SPECLINES_Mg_II_2795,
+ GAL_SPECLINES_Mg_II_2802,
+ GAL_SPECLINES_Fe_IV_2829,
+ GAL_SPECLINES_Fe_IV_2835,
+ GAL_SPECLINES_Ar_IV_2853,
+ GAL_SPECLINES_Ar_IV_2868,
+ GAL_SPECLINES_Mg_V_2928,
+ GAL_SPECLINES_He_I_2945,
+ GAL_SPECLINES_O_III_3132,
+ GAL_SPECLINES_He_I_3187,
+ GAL_SPECLINES_He_II_3203,
+ GAL_SPECLINES_O_III_3312,
+ GAL_SPECLINES_Ne_V_3345,
+ GAL_SPECLINES_Ne_V_3425,
+ GAL_SPECLINES_O_III_3444,
+ GAL_SPECLINES_N_I_3466_4,
+ GAL_SPECLINES_N_I_3466_5,
+ GAL_SPECLINES_He_I_3487,
+ GAL_SPECLINES_Fe_VII_3586,
+ GAL_SPECLINES_Fe_VI_3662,
+ GAL_SPECLINES_H_19,
+ GAL_SPECLINES_H_18,
+ GAL_SPECLINES_H_17,
+ GAL_SPECLINES_H_16,
+ GAL_SPECLINES_H_15,
+ GAL_SPECLINES_H_14,
+ GAL_SPECLINES_O_II_3726,
+ GAL_SPECLINES_O_II_3728,
+ GAL_SPECLINES_H_13,
+ GAL_SPECLINES_H_12,
+ GAL_SPECLINES_Fe_VII_3758,
+ GAL_SPECLINES_H_11,
+ GAL_SPECLINES_H_10,
+ GAL_SPECLINES_H_9,
+ GAL_SPECLINES_Fe_V_3839,
+ GAL_SPECLINES_Ne_III_3868,
+ GAL_SPECLINES_He_I_3888,
+ GAL_SPECLINES_H_8,
+ GAL_SPECLINES_Fe_V_3891,
+ GAL_SPECLINES_Fe_V_3911,
+ GAL_SPECLINES_Ne_III_3967,
+ GAL_SPECLINES_H_epsilon,
+ GAL_SPECLINES_He_I_4026,
+ GAL_SPECLINES_S_II_4068,
+ GAL_SPECLINES_Fe_V_4071,
+ GAL_SPECLINES_S_II_4076,
+ GAL_SPECLINES_H_delta,
+ GAL_SPECLINES_He_I_4143,
+ GAL_SPECLINES_Fe_II_4178,
+ GAL_SPECLINES_Fe_V_4180,
+ GAL_SPECLINES_Fe_II_4233,
+ GAL_SPECLINES_Fe_V_4227,
+ GAL_SPECLINES_Fe_II_4287,
+ GAL_SPECLINES_Fe_II_4304,
+ GAL_SPECLINES_O_II_4317,
+ GAL_SPECLINES_H_gamma,
+ GAL_SPECLINES_O_III_4363,
+ GAL_SPECLINES_Ar_XIV,
+ GAL_SPECLINES_O_II_4414,
+ GAL_SPECLINES_Fe_II_4416,
+ GAL_SPECLINES_Fe_II_4452,
+ GAL_SPECLINES_He_I_4471,
+ GAL_SPECLINES_Fe_II_4489,
+ GAL_SPECLINES_Fe_II_4491,
+ GAL_SPECLINES_N_III_4510,
+ GAL_SPECLINES_Fe_II_4522,
+ GAL_SPECLINES_Fe_II_4555,
+ GAL_SPECLINES_Fe_II_4582,
+ GAL_SPECLINES_Fe_II_4583,
+ GAL_SPECLINES_Fe_II_4629,
+ GAL_SPECLINES_N_III_4634,
+ GAL_SPECLINES_N_III_4640,
+ GAL_SPECLINES_N_III_4641,
+ GAL_SPECLINES_C_III_4647,
+ GAL_SPECLINES_C_III_4650,
+ GAL_SPECLINES_C_III_5651,
+ GAL_SPECLINES_Fe_III_4658,
+ GAL_SPECLINES_He_II_4685,
+ GAL_SPECLINES_Ar_IV_4711,
+ GAL_SPECLINES_Ar_IV_4740,
+ GAL_SPECLINES_H_beta,
+ GAL_SPECLINES_Fe_VII_4893,
+ GAL_SPECLINES_Fe_IV_4903,
+ GAL_SPECLINES_Fe_II_4923,
+ GAL_SPECLINES_O_III_4958,
+ GAL_SPECLINES_O_III_5006,
+ GAL_SPECLINES_Fe_II_5018,
+ GAL_SPECLINES_Fe_III_5084,
+ GAL_SPECLINES_Fe_VI_5145,
+ GAL_SPECLINES_Fe_VII_5158,
+ GAL_SPECLINES_Fe_II_5169,
+ GAL_SPECLINES_Fe_VI_5176,
+ GAL_SPECLINES_Fe_II_5197,
+ GAL_SPECLINES_N_I_5200,
+ GAL_SPECLINES_Fe_II_5234,
+ GAL_SPECLINES_Fe_IV_5236,
+ GAL_SPECLINES_Fe_III_5270,
+ GAL_SPECLINES_Fe_II_5276,
+ GAL_SPECLINES_Fe_VII_5276,
+ GAL_SPECLINES_Fe_XIV,
+ GAL_SPECLINES_Ca_V,
+ GAL_SPECLINES_Fe_II_5316_6,
+ GAL_SPECLINES_Fe_II_5316_7,
+ GAL_SPECLINES_Fe_VI_5335,
+ GAL_SPECLINES_Fe_VI_5424,
+ GAL_SPECLINES_Cl_III_5517,
+ GAL_SPECLINES_Cl_III_5537,
+ GAL_SPECLINES_Fe_VI_5637,
+ GAL_SPECLINES_Fe_VI_5677,
+ GAL_SPECLINES_C_III_5697,
+ GAL_SPECLINES_Fe_VII_5720,
+ GAL_SPECLINES_N_II_5754,
+ GAL_SPECLINES_C_IV_5801,
+ GAL_SPECLINES_C_IV_5811,
+ GAL_SPECLINES_He_I_5875,
+ GAL_SPECLINES_O_I_6046,
+ GAL_SPECLINES_Fe_VII_6087,
+ GAL_SPECLINES_O_I_6300,
+ GAL_SPECLINES_S_III_6312,
+ GAL_SPECLINES_Si_II_6347,
+ GAL_SPECLINES_O_I_6363,
+ GAL_SPECLINES_Fe_II_6369,
+ GAL_SPECLINES_Fe_X,
+ GAL_SPECLINES_Fe_II_6516,
+ GAL_SPECLINES_N_II_6548,
+ GAL_SPECLINES_H_alpha,
+ GAL_SPECLINES_N_II_6583,
+ GAL_SPECLINES_S_II_6716,
+ GAL_SPECLINES_S_II_6730,
+ GAL_SPECLINES_O_I_7002,
+ GAL_SPECLINES_Ar_V,
+ GAL_SPECLINES_He_I_7065,
+ GAL_SPECLINES_Ar_III_7135,
+ GAL_SPECLINES_Fe_II_7155,
+ GAL_SPECLINES_Ar_IV_7170,
+ GAL_SPECLINES_Fe_II_7172,
+ GAL_SPECLINES_C_II_7236,
+ GAL_SPECLINES_Ar_IV_7237,
+ GAL_SPECLINES_O_I_7254,
+ GAL_SPECLINES_Ar_IV_7262,
+ GAL_SPECLINES_He_I_7281,
+ GAL_SPECLINES_O_II_7319,
+ GAL_SPECLINES_O_II_7330,
+ GAL_SPECLINES_Ni_II_7377,
+ GAL_SPECLINES_Ni_II_7411,
+ GAL_SPECLINES_Fe_II_7452,
+ GAL_SPECLINES_N_I_7468,
+ GAL_SPECLINES_S_XII,
+ GAL_SPECLINES_Ar_III_7751,
+ GAL_SPECLINES_He_I_7816,
+ GAL_SPECLINES_Ar_I_7868,
+ GAL_SPECLINES_Ni_III,
+ GAL_SPECLINES_Fe_XI_7891,
+ GAL_SPECLINES_He_II_8236,
+ GAL_SPECLINES_Pa_20,
+ GAL_SPECLINES_Pa_19,
+ GAL_SPECLINES_Pa_18,
+ GAL_SPECLINES_O_I_8446,
+ GAL_SPECLINES_Pa_17,
+ GAL_SPECLINES_Ca_II_8498,
+ GAL_SPECLINES_Pa_16,
+ GAL_SPECLINES_Ca_II_8542,
+ GAL_SPECLINES_Pa_15,
+ GAL_SPECLINES_Cl_II,
+ GAL_SPECLINES_Pa_14,
+ GAL_SPECLINES_Fe_II_8616,
+ GAL_SPECLINES_Ca_II_8662,
+ GAL_SPECLINES_Pa_13,
+ GAL_SPECLINES_N_I_8680,
+ GAL_SPECLINES_N_I_8703,
+ GAL_SPECLINES_N_I_8711,
+ GAL_SPECLINES_Pa_12,
+ GAL_SPECLINES_Pa_11,
+ GAL_SPECLINES_Fe_II_8891,
+ GAL_SPECLINES_Pa_10,
+ GAL_SPECLINES_S_III_9068,
+ GAL_SPECLINES_Pa_9,
+ GAL_SPECLINES_S_III_9531,
+ GAL_SPECLINES_Pa_epsilon,
+ GAL_SPECLINES_C_I_9824,
+ GAL_SPECLINES_C_I_9850,
+ GAL_SPECLINES_S_VIII,
+ GAL_SPECLINES_He_I_10027,
+ GAL_SPECLINES_He_I_10031,
+ GAL_SPECLINES_Pa_delta,
+ GAL_SPECLINES_S_II_10286,
+ GAL_SPECLINES_S_II_10320,
+ GAL_SPECLINES_S_II_10336,
+ GAL_SPECLINES_Fe_XIII,
+ GAL_SPECLINES_He_I_10830,
+ GAL_SPECLINES_Pa_gamma,
/* This should be the last element (to keep the total number of
lines). */
- GAL_SPECLINES_INVALID_MAX,
+ GAL_SPECLINES_NUMBER
};
-/* Spectral lines wavelengths in Angstroms (SORT BY WAVELENGTH). */
-#define GAL_SPECLINES_ANGSTROM_SIIRED 6731
-#define GAL_SPECLINES_ANGSTROM_SII 6724
-#define GAL_SPECLINES_ANGSTROM_SIIBLUE 6717
-#define GAL_SPECLINES_ANGSTROM_NIIRED 6584
-#define GAL_SPECLINES_ANGSTROM_NII 6566
-#define GAL_SPECLINES_ANGSTROM_HALPHA 6562.8
-#define GAL_SPECLINES_ANGSTROM_NIIBLUE 6548
-#define GAL_SPECLINES_ANGSTROM_OIIIRED_VIS 5007
-#define GAL_SPECLINES_ANGSTROM_OIII_VIS 4983
-#define GAL_SPECLINES_ANGSTROM_OIIIBLUE_VIS 4959
-#define GAL_SPECLINES_ANGSTROM_HBETA 4861.36
-#define GAL_SPECLINES_ANGSTROM_HEII_VIS 4686
-#define GAL_SPECLINES_ANGSTROM_HGAMMA 4340.46
-#define GAL_SPECLINES_ANGSTROM_HDELTA 4101.74
-#define GAL_SPECLINES_ANGSTROM_HEPSILON 3970.07
-#define GAL_SPECLINES_ANGSTROM_NEIII 3869
-#define GAL_SPECLINES_ANGSTROM_OIIRED 3729
-#define GAL_SPECLINES_ANGSTROM_OII 3727.5
-#define GAL_SPECLINES_ANGSTROM_OIIBLUE 3726
-#define GAL_SPECLINES_ANGSTROM_BLIMIT 3646
-#define GAL_SPECLINES_ANGSTROM_MGIIRED 2803
-#define GAL_SPECLINES_ANGSTROM_MGII 2799.5
-#define GAL_SPECLINES_ANGSTROM_MGIIBLUE 2796
-#define GAL_SPECLINES_ANGSTROM_CIIIRED 1909
-#define GAL_SPECLINES_ANGSTROM_CIII 1908
-#define GAL_SPECLINES_ANGSTROM_CIIIBLUE 1907
-#define GAL_SPECLINES_ANGSTROM_SiIIIRED 1892
-#define GAL_SPECLINES_ANGSTROM_SiIII 1887.5
-#define GAL_SPECLINES_ANGSTROM_SiIIIBLUE 1883
-#define GAL_SPECLINES_ANGSTROM_OIIIRED_UV 1666
-#define GAL_SPECLINES_ANGSTROM_OIII_UV 1663.5
-#define GAL_SPECLINES_ANGSTROM_OIIIBLUE_UV 1661
-#define GAL_SPECLINES_ANGSTROM_HEII_UV 1640
-#define GAL_SPECLINES_ANGSTROM_CIVRED 1551
-#define GAL_SPECLINES_ANGSTROM_CIV 1549.5
-#define GAL_SPECLINES_ANGSTROM_CIVBLUE 1548
-#define GAL_SPECLINES_ANGSTROM_NV 1240
-#define GAL_SPECLINES_ANGSTROM_LYALPHA 1215.67
-#define GAL_SPECLINES_ANGSTROM_LYBETA 1025.7
-#define GAL_SPECLINES_ANGSTROM_LYGAMMA 972.54
-#define GAL_SPECLINES_ANGSTROM_LYDELTA 949.74
-#define GAL_SPECLINES_ANGSTROM_LYEPSILON 937.80
-#define GAL_SPECLINES_ANGSTROM_LYLIMIT 912
-/* Spectral line name strings (SORT BY WAVELENGTH). */
-#define GAL_SPECLINES_NAME_SIIRED "siired"
-#define GAL_SPECLINES_NAME_SII "sii"
-#define GAL_SPECLINES_NAME_SIIBLUE "siiblue"
-#define GAL_SPECLINES_NAME_NIIRED "niired"
-#define GAL_SPECLINES_NAME_NII "nii"
-#define GAL_SPECLINES_NAME_HALPHA "halpha"
-#define GAL_SPECLINES_NAME_NIIBLUE "niiblue"
-#define GAL_SPECLINES_NAME_OIIIRED_VIS "oiiired-vis"
-#define GAL_SPECLINES_NAME_OIII_VIS "oiii-vis"
-#define GAL_SPECLINES_NAME_OIIIBLUE_VIS "oiiiblue-vis"
-#define GAL_SPECLINES_NAME_HBETA "hbeta"
-#define GAL_SPECLINES_NAME_HEII_VIS "heii-vis"
-#define GAL_SPECLINES_NAME_HGAMMA "hgamma"
-#define GAL_SPECLINES_NAME_HDELTA "hdelta"
-#define GAL_SPECLINES_NAME_HEPSILON "hepsilon"
-#define GAL_SPECLINES_NAME_NEIII "neiii"
-#define GAL_SPECLINES_NAME_OIIRED "oiired"
-#define GAL_SPECLINES_NAME_OII "oii"
-#define GAL_SPECLINES_NAME_OIIBLUE "oiiblue"
-#define GAL_SPECLINES_NAME_BLIMIT "blimit"
-#define GAL_SPECLINES_NAME_MGIIRED "mgiired"
-#define GAL_SPECLINES_NAME_MGII "mgii"
-#define GAL_SPECLINES_NAME_MGIIBLUE "mgiiblue"
-#define GAL_SPECLINES_NAME_CIIIRED "ciiired"
-#define GAL_SPECLINES_NAME_CIII "ciii"
-#define GAL_SPECLINES_NAME_CIIIBLUE "ciiiblue"
-#define GAL_SPECLINES_NAME_SiIIIRED "si_iiired"
-#define GAL_SPECLINES_NAME_SiIII "si_iii"
-#define GAL_SPECLINES_NAME_SiIIIBLUE "si_iiiblue"
-#define GAL_SPECLINES_NAME_OIIIRED_UV "oiiired-uv"
-#define GAL_SPECLINES_NAME_OIII_UV "oiii-uv"
-#define GAL_SPECLINES_NAME_OIIIBLUE_UV "oiiiblue-uv"
-#define GAL_SPECLINES_NAME_HEII_UV "heii-uv"
-#define GAL_SPECLINES_NAME_CIVRED "civred"
-#define GAL_SPECLINES_NAME_CIV "civ"
-#define GAL_SPECLINES_NAME_CIVBLUE "civblue"
-#define GAL_SPECLINES_NAME_NV "nv"
-#define GAL_SPECLINES_NAME_LYALPHA "lyalpha"
-#define GAL_SPECLINES_NAME_LYBETA "lybeta"
-#define GAL_SPECLINES_NAME_LYGAMMA "lygamma"
-#define GAL_SPECLINES_NAME_LYDELTA "lydelta"
-#define GAL_SPECLINES_NAME_LYEPSILON "lyepsilon"
-#define GAL_SPECLINES_NAME_LYLIMIT "lylimit"
+
+enum gal_speclines_limit_codes
+{
+ /* Allowing '0' to be identied as a known-non-line. */
+ GAL_SPECLINES_LIMIT_INVALID=0,
+
+ GAL_SPECLINES_LIMIT_LYMAN=GAL_SPECLINES_NUMBER,
+ GAL_SPECLINES_LIMIT_BALMER,
+ GAL_SPECLINES_LIMIT_PASCHEN,
+
+ /* Total number of limits and lines+limits. */
+ GAL_SPECLINES_LIMIT_NUMBERWITHLINES,
+ GAL_SPECLINES_LIMIT_NUMBER = (GAL_SPECLINES_LIMIT_NUMBERWITHLINES
+ - GAL_SPECLINES_LIMIT_LYMAN)
+};
+/* Spectral lines wavelengths in Angstroms (SORT BY WAVELENGTH).
+ Source: http://astronomy.nmsu.edu/drewski/tableofemissionlines.html
+
+ The following extra lines have been added:
+ - Ly-gamma (https://en.wikipedia.org/wiki/Lyman_series) */
+#define GAL_SPECLINES_ANGSTROM_Ne_VIII_770 770.409
+#define GAL_SPECLINES_ANGSTROM_Ne_VIII_780 780.324
+#define GAL_SPECLINES_ANGSTROM_Ly_epsilon 937.814
+#define GAL_SPECLINES_ANGSTROM_Ly_delta 949.742
+#define GAL_SPECLINES_ANGSTROM_Ly_gamma 972.536
+#define GAL_SPECLINES_ANGSTROM_C_III_977 977.030
+#define GAL_SPECLINES_ANGSTROM_N_III_989 989.790
+#define GAL_SPECLINES_ANGSTROM_N_III_991_51 991.514
+#define GAL_SPECLINES_ANGSTROM_N_III_991_57 991.579
+#define GAL_SPECLINES_ANGSTROM_Ly_beta 1025.722
+#define GAL_SPECLINES_ANGSTROM_O_VI_1031 1031.912
+#define GAL_SPECLINES_ANGSTROM_O_VI_1037 1037.613
+#define GAL_SPECLINES_ANGSTROM_Ar_I_1066 1066.660
+#define GAL_SPECLINES_ANGSTROM_Ly_alpha 1215.670
+#define GAL_SPECLINES_ANGSTROM_N_V_1238 1238.821
+#define GAL_SPECLINES_ANGSTROM_N_V_1242 1242.804
+#define GAL_SPECLINES_ANGSTROM_Si_II_1260 1260.422
+#define GAL_SPECLINES_ANGSTROM_Si_II_1264 1264.730
+#define GAL_SPECLINES_ANGSTROM_O_I_1302 1302.168
+#define GAL_SPECLINES_ANGSTROM_C_II_1334 1334.532
+#define GAL_SPECLINES_ANGSTROM_C_II_1335 1335.708
+#define GAL_SPECLINES_ANGSTROM_Si_IV_1393 1393.755
+#define GAL_SPECLINES_ANGSTROM_O_IV_1397 1397.232
+#define GAL_SPECLINES_ANGSTROM_O_IV_1399 1399.780
+#define GAL_SPECLINES_ANGSTROM_Si_IV_1402 1402.770
+#define GAL_SPECLINES_ANGSTROM_N_IV_1486 1486.496
+#define GAL_SPECLINES_ANGSTROM_C_IV_1548 1548.187
+#define GAL_SPECLINES_ANGSTROM_C_IV_1550 1550.772
+#define GAL_SPECLINES_ANGSTROM_He_II_1640 1640.420
+#define GAL_SPECLINES_ANGSTROM_O_III_1660 1660.809
+#define GAL_SPECLINES_ANGSTROM_O_III_1666 1666.150
+#define GAL_SPECLINES_ANGSTROM_N_III_1746 1746.823
+#define GAL_SPECLINES_ANGSTROM_N_III_1748 1748.656
+#define GAL_SPECLINES_ANGSTROM_Al_III_1854 1854.716
+#define GAL_SPECLINES_ANGSTROM_Al_III_1862 1862.790
+#define GAL_SPECLINES_ANGSTROM_Si_III 1892.030
+#define GAL_SPECLINES_ANGSTROM_C_III_1908 1908.734
+#define GAL_SPECLINES_ANGSTROM_N_II_2142 2142.780
+#define GAL_SPECLINES_ANGSTROM_O_III_2320 2320.951
+#define GAL_SPECLINES_ANGSTROM_C_II_2323 2323.500
+#define GAL_SPECLINES_ANGSTROM_C_II_2324 2324.690
+#define GAL_SPECLINES_ANGSTROM_Fe_XI_2648 2648.710
+#define GAL_SPECLINES_ANGSTROM_He_II_2733 2733.289
+#define GAL_SPECLINES_ANGSTROM_Mg_V_2782 2782.700
+#define GAL_SPECLINES_ANGSTROM_Mg_II_2795 2795.528
+#define GAL_SPECLINES_ANGSTROM_Mg_II_2802 2802.705
+#define GAL_SPECLINES_ANGSTROM_Fe_IV_2829 2829.360
+#define GAL_SPECLINES_ANGSTROM_Fe_IV_2835 2835.740
+#define GAL_SPECLINES_ANGSTROM_Ar_IV_2853 2853.670
+#define GAL_SPECLINES_ANGSTROM_Ar_IV_2868 2868.210
+#define GAL_SPECLINES_ANGSTROM_Mg_V_2928 2928.000
+#define GAL_SPECLINES_ANGSTROM_He_I_2945 2945.106
+#define GAL_SPECLINES_ANGSTROM_O_III_3132 3132.794
+#define GAL_SPECLINES_ANGSTROM_He_I_3187 3187.745
+#define GAL_SPECLINES_ANGSTROM_He_II_3203 3203.100
+#define GAL_SPECLINES_ANGSTROM_O_III_3312 3312.329
+#define GAL_SPECLINES_ANGSTROM_Ne_V_3345 3345.821
+#define GAL_SPECLINES_ANGSTROM_Ne_V_3425 3425.881
+#define GAL_SPECLINES_ANGSTROM_O_III_3444 3444.052
+#define GAL_SPECLINES_ANGSTROM_N_I_3466_4 3466.497
+#define GAL_SPECLINES_ANGSTROM_N_I_3466_5 3466.543
+#define GAL_SPECLINES_ANGSTROM_He_I_3487 3487.727
+#define GAL_SPECLINES_ANGSTROM_Fe_VII_3586 3586.320
+#define GAL_SPECLINES_ANGSTROM_Fe_VI_3662 3662.500
+#define GAL_SPECLINES_ANGSTROM_H_19 3686.831
+#define GAL_SPECLINES_ANGSTROM_H_18 3691.551
+#define GAL_SPECLINES_ANGSTROM_H_17 3697.157
+#define GAL_SPECLINES_ANGSTROM_H_16 3703.859
+#define GAL_SPECLINES_ANGSTROM_H_15 3711.977
+#define GAL_SPECLINES_ANGSTROM_H_14 3721.945
+#define GAL_SPECLINES_ANGSTROM_O_II_3726 3726.032
+#define GAL_SPECLINES_ANGSTROM_O_II_3728 3728.815
+#define GAL_SPECLINES_ANGSTROM_H_13 3734.369
+#define GAL_SPECLINES_ANGSTROM_H_12 3750.158
+#define GAL_SPECLINES_ANGSTROM_Fe_VII_3758 3758.920
+#define GAL_SPECLINES_ANGSTROM_H_11 3770.637
+#define GAL_SPECLINES_ANGSTROM_H_10 3797.904
+#define GAL_SPECLINES_ANGSTROM_H_9 3835.391
+#define GAL_SPECLINES_ANGSTROM_Fe_V_3839 3839.270
+#define GAL_SPECLINES_ANGSTROM_Ne_III_3868 3868.760
+#define GAL_SPECLINES_ANGSTROM_He_I_3888 3888.647
+#define GAL_SPECLINES_ANGSTROM_H_8 3889.064
+#define GAL_SPECLINES_ANGSTROM_Fe_V_3891 3891.280
+#define GAL_SPECLINES_ANGSTROM_Fe_V_3911 3911.330
+#define GAL_SPECLINES_ANGSTROM_Ne_III_3967 3967.470
+#define GAL_SPECLINES_ANGSTROM_H_epsilon 3970.079
+#define GAL_SPECLINES_ANGSTROM_He_I_4026 4026.190
+#define GAL_SPECLINES_ANGSTROM_S_II_4068 4068.600
+#define GAL_SPECLINES_ANGSTROM_Fe_V_4071 4071.240
+#define GAL_SPECLINES_ANGSTROM_S_II_4076 4076.349
+#define GAL_SPECLINES_ANGSTROM_H_delta 4101.742
+#define GAL_SPECLINES_ANGSTROM_He_I_4143 4143.761
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4178 4178.862
+#define GAL_SPECLINES_ANGSTROM_Fe_V_4180 4180.600
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4233 4233.172
+#define GAL_SPECLINES_ANGSTROM_Fe_V_4227 4227.190
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4287 4287.394
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4304 4303.176
+#define GAL_SPECLINES_ANGSTROM_O_II_4317 4317.139
+#define GAL_SPECLINES_ANGSTROM_H_gamma 4340.471
+#define GAL_SPECLINES_ANGSTROM_O_III_4363 4363.210
+#define GAL_SPECLINES_ANGSTROM_Ar_XIV 4412.300
+#define GAL_SPECLINES_ANGSTROM_O_II_4414 4414.899
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4416 4416.830
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4452 4452.098
+#define GAL_SPECLINES_ANGSTROM_He_I_4471 4471.479
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4489 4489.183
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4491 4491.405
+#define GAL_SPECLINES_ANGSTROM_N_III_4510 4510.910
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4522 4522.634
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4555 4555.893
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4582 4582.835
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4583 4583.837
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4629 4629.339
+#define GAL_SPECLINES_ANGSTROM_N_III_4634 4634.140
+#define GAL_SPECLINES_ANGSTROM_N_III_4640 4640.640
+#define GAL_SPECLINES_ANGSTROM_N_III_4641 4641.850
+#define GAL_SPECLINES_ANGSTROM_C_III_4647 4647.420
+#define GAL_SPECLINES_ANGSTROM_C_III_4650 4650.250
+#define GAL_SPECLINES_ANGSTROM_C_III_5651 4651.470
+#define GAL_SPECLINES_ANGSTROM_Fe_III_4658 4658.050
+#define GAL_SPECLINES_ANGSTROM_He_II_4685 4685.710
+#define GAL_SPECLINES_ANGSTROM_Ar_IV_4711 4711.260
+#define GAL_SPECLINES_ANGSTROM_Ar_IV_4740 4740.120
+#define GAL_SPECLINES_ANGSTROM_H_beta 4861.333
+#define GAL_SPECLINES_ANGSTROM_Fe_VII_4893 4893.370
+#define GAL_SPECLINES_ANGSTROM_Fe_IV_4903 4903.070
+#define GAL_SPECLINES_ANGSTROM_Fe_II_4923 4923.927
+#define GAL_SPECLINES_ANGSTROM_O_III_4958 4958.911
+#define GAL_SPECLINES_ANGSTROM_O_III_5006 5006.843
+#define GAL_SPECLINES_ANGSTROM_Fe_II_5018 5018.440
+#define GAL_SPECLINES_ANGSTROM_Fe_III_5084 5084.770
+#define GAL_SPECLINES_ANGSTROM_Fe_VI_5145 5145.750
+#define GAL_SPECLINES_ANGSTROM_Fe_VII_5158 5158.890
+#define GAL_SPECLINES_ANGSTROM_Fe_II_5169 5169.033
+#define GAL_SPECLINES_ANGSTROM_Fe_VI_5176 5176.040
+#define GAL_SPECLINES_ANGSTROM_Fe_II_5197 5197.577
+#define GAL_SPECLINES_ANGSTROM_N_I_5200 5200.257
+#define GAL_SPECLINES_ANGSTROM_Fe_II_5234 5234.625
+#define GAL_SPECLINES_ANGSTROM_Fe_IV_5236 5236.060
+#define GAL_SPECLINES_ANGSTROM_Fe_III_5270 5270.400
+#define GAL_SPECLINES_ANGSTROM_Fe_II_5276 5276.002
+#define GAL_SPECLINES_ANGSTROM_Fe_VII_5276 5276.380
+#define GAL_SPECLINES_ANGSTROM_Fe_XIV 5302.860
+#define GAL_SPECLINES_ANGSTROM_Ca_V 5309.110
+#define GAL_SPECLINES_ANGSTROM_Fe_II_5316_6 5316.615
+#define GAL_SPECLINES_ANGSTROM_Fe_II_5316_7 5316.784
+#define GAL_SPECLINES_ANGSTROM_Fe_VI_5335 5335.180
+#define GAL_SPECLINES_ANGSTROM_Fe_VI_5424 5424.220
+#define GAL_SPECLINES_ANGSTROM_Cl_III_5517 5517.709
+#define GAL_SPECLINES_ANGSTROM_Cl_III_5537 5537.873
+#define GAL_SPECLINES_ANGSTROM_Fe_VI_5637 5637.600
+#define GAL_SPECLINES_ANGSTROM_Fe_VI_5677 5677.000
+#define GAL_SPECLINES_ANGSTROM_C_III_5697 5695.920
+#define GAL_SPECLINES_ANGSTROM_Fe_VII_5720 5720.700
+#define GAL_SPECLINES_ANGSTROM_N_II_5754 5754.590
+#define GAL_SPECLINES_ANGSTROM_C_IV_5801 5801.330
+#define GAL_SPECLINES_ANGSTROM_C_IV_5811 5811.980
+#define GAL_SPECLINES_ANGSTROM_He_I_5875 5875.624
+#define GAL_SPECLINES_ANGSTROM_O_I_6046 6046.440
+#define GAL_SPECLINES_ANGSTROM_Fe_VII_6087 6087.000
+#define GAL_SPECLINES_ANGSTROM_O_I_6300 6300.304
+#define GAL_SPECLINES_ANGSTROM_S_III_6312 6312.060
+#define GAL_SPECLINES_ANGSTROM_Si_II_6347 6347.100
+#define GAL_SPECLINES_ANGSTROM_O_I_6363 6363.776
+#define GAL_SPECLINES_ANGSTROM_Fe_II_6369 6369.462
+#define GAL_SPECLINES_ANGSTROM_Fe_X 6374.510
+#define GAL_SPECLINES_ANGSTROM_Fe_II_6516 6516.081
+#define GAL_SPECLINES_ANGSTROM_N_II_6548 6548.050
+#define GAL_SPECLINES_ANGSTROM_H_alpha 6562.819
+#define GAL_SPECLINES_ANGSTROM_N_II_6583 6583.460
+#define GAL_SPECLINES_ANGSTROM_S_II_6716 6716.440
+#define GAL_SPECLINES_ANGSTROM_S_II_6730 6730.810
+#define GAL_SPECLINES_ANGSTROM_O_I_7002 7002.230
+#define GAL_SPECLINES_ANGSTROM_Ar_V 7005.870
+#define GAL_SPECLINES_ANGSTROM_He_I_7065 7065.196
+#define GAL_SPECLINES_ANGSTROM_Ar_III_7135 7135.790
+#define GAL_SPECLINES_ANGSTROM_Fe_II_7155 7155.157
+#define GAL_SPECLINES_ANGSTROM_Ar_IV_7170 7170.620
+#define GAL_SPECLINES_ANGSTROM_Fe_II_7172 7172.000
+#define GAL_SPECLINES_ANGSTROM_C_II_7236 7236.420
+#define GAL_SPECLINES_ANGSTROM_Ar_IV_7237 7237.260
+#define GAL_SPECLINES_ANGSTROM_O_I_7254 7254.448
+#define GAL_SPECLINES_ANGSTROM_Ar_IV_7262 7262.760
+#define GAL_SPECLINES_ANGSTROM_He_I_7281 7281.349
+#define GAL_SPECLINES_ANGSTROM_O_II_7319 7319.990
+#define GAL_SPECLINES_ANGSTROM_O_II_7330 7330.730
+#define GAL_SPECLINES_ANGSTROM_Ni_II_7377 7377.830
+#define GAL_SPECLINES_ANGSTROM_Ni_II_7411 7411.160
+#define GAL_SPECLINES_ANGSTROM_Fe_II_7452 7452.538
+#define GAL_SPECLINES_ANGSTROM_N_I_7468 7468.310
+#define GAL_SPECLINES_ANGSTROM_S_XII 7611.000
+#define GAL_SPECLINES_ANGSTROM_Ar_III_7751 7751.060
+#define GAL_SPECLINES_ANGSTROM_He_I_7816 7816.136
+#define GAL_SPECLINES_ANGSTROM_Ar_I_7868 7868.194
+#define GAL_SPECLINES_ANGSTROM_Ni_III 7889.900
+#define GAL_SPECLINES_ANGSTROM_Fe_XI_7891 7891.800
+#define GAL_SPECLINES_ANGSTROM_He_II_8236 8236.790
+#define GAL_SPECLINES_ANGSTROM_Pa_20 8392.397
+#define GAL_SPECLINES_ANGSTROM_Pa_19 8413.318
+#define GAL_SPECLINES_ANGSTROM_Pa_18 8437.956
+#define GAL_SPECLINES_ANGSTROM_O_I_8446 8446.359
+#define GAL_SPECLINES_ANGSTROM_Pa_17 8467.254
+#define GAL_SPECLINES_ANGSTROM_Ca_II_8498 8498.020
+#define GAL_SPECLINES_ANGSTROM_Pa_16 8502.483
+#define GAL_SPECLINES_ANGSTROM_Ca_II_8542 8542.090
+#define GAL_SPECLINES_ANGSTROM_Pa_15 8545.383
+#define GAL_SPECLINES_ANGSTROM_Cl_II 8578.700
+#define GAL_SPECLINES_ANGSTROM_Pa_14 8598.392
+#define GAL_SPECLINES_ANGSTROM_Fe_II_8616 8616.950
+#define GAL_SPECLINES_ANGSTROM_Ca_II_8662 8662.140
+#define GAL_SPECLINES_ANGSTROM_Pa_13 8665.019
+#define GAL_SPECLINES_ANGSTROM_N_I_8680 8680.282
+#define GAL_SPECLINES_ANGSTROM_N_I_8703 8703.247
+#define GAL_SPECLINES_ANGSTROM_N_I_8711 8711.703
+#define GAL_SPECLINES_ANGSTROM_Pa_12 8750.472
+#define GAL_SPECLINES_ANGSTROM_Pa_11 8862.782
+#define GAL_SPECLINES_ANGSTROM_Fe_II_8891 8891.910
+#define GAL_SPECLINES_ANGSTROM_Pa_10 9014.909
+#define GAL_SPECLINES_ANGSTROM_S_III_9068 9068.600
+#define GAL_SPECLINES_ANGSTROM_Pa_9 9229.014
+#define GAL_SPECLINES_ANGSTROM_S_III_9531 9531.100
+#define GAL_SPECLINES_ANGSTROM_Pa_epsilon 9545.969
+#define GAL_SPECLINES_ANGSTROM_C_I_9824 9824.130
+#define GAL_SPECLINES_ANGSTROM_C_I_9850 9850.260
+#define GAL_SPECLINES_ANGSTROM_S_VIII 9913.000
+#define GAL_SPECLINES_ANGSTROM_He_I_10027 10027.730
+#define GAL_SPECLINES_ANGSTROM_He_I_10031 10031.160
+#define GAL_SPECLINES_ANGSTROM_Pa_delta 10049.368
+#define GAL_SPECLINES_ANGSTROM_S_II_10286 10286.730
+#define GAL_SPECLINES_ANGSTROM_S_II_10320 10320.490
+#define GAL_SPECLINES_ANGSTROM_S_II_10336 10336.410
+#define GAL_SPECLINES_ANGSTROM_Fe_XIII 10746.800
+#define GAL_SPECLINES_ANGSTROM_He_I_10830 10830.340
+#define GAL_SPECLINES_ANGSTROM_Pa_gamma 10938.086
+
+/* Common limits of line series; from
+ https://en.wikipedia.org/wiki/Hydrogen_spectral_series */
+#define GAL_SPECLINES_ANGSTROM_LIMIT_LYMAN 912
+#define GAL_SPECLINES_ANGSTROM_LIMIT_BALMER 3646
+#define GAL_SPECLINES_ANGSTROM_LIMIT_PASCHEN 8204
+
+
+
+/* Spectral line name strings (SORT BY WAVELENGTH). */
+#define GAL_SPECLINES_NAME_Ne_VIII_770 "Ne-VIII-770"
+#define GAL_SPECLINES_NAME_Ne_VIII_780 "Ne-VIII-780"
+#define GAL_SPECLINES_NAME_Ly_epsilon "Ly-epsilon"
+#define GAL_SPECLINES_NAME_Ly_delta "Ly-delta"
+#define GAL_SPECLINES_NAME_Ly_gamma "Ly-gamma"
+#define GAL_SPECLINES_NAME_C_III_977 "C-III-977"
+#define GAL_SPECLINES_NAME_N_III_989 "N-III-989"
+#define GAL_SPECLINES_NAME_N_III_991_51 "N-III-991.51"
+#define GAL_SPECLINES_NAME_N_III_991_57 "N-III-991.57"
+#define GAL_SPECLINES_NAME_Ly_beta "Ly-beta"
+#define GAL_SPECLINES_NAME_O_VI_1031 "O-VI-1031"
+#define GAL_SPECLINES_NAME_O_VI_1037 "O-VI-1037"
+#define GAL_SPECLINES_NAME_Ar_I_1066 "Ar-I-1066"
+#define GAL_SPECLINES_NAME_Ly_alpha "Ly-alpha"
+#define GAL_SPECLINES_NAME_N_V_1238 "N-V-1238"
+#define GAL_SPECLINES_NAME_N_V_1242 "N-V-1242"
+#define GAL_SPECLINES_NAME_Si_II_1260 "Si-II-1260"
+#define GAL_SPECLINES_NAME_Si_II_1264 "Si_II-1302"
+#define GAL_SPECLINES_NAME_O_I_1302 "O-I-1302"
+#define GAL_SPECLINES_NAME_C_II_1334 "C-II-1334"
+#define GAL_SPECLINES_NAME_C_II_1335 "C-II-1335"
+#define GAL_SPECLINES_NAME_Si_IV_1393 "Si-IV-1393"
+#define GAL_SPECLINES_NAME_O_IV_1397 "O-IV-1397"
+#define GAL_SPECLINES_NAME_O_IV_1399 "O-IV-1399"
+#define GAL_SPECLINES_NAME_Si_IV_1402 "Si-IV-1402"
+#define GAL_SPECLINES_NAME_N_IV_1486 "N-IV-1486"
+#define GAL_SPECLINES_NAME_C_IV_1548 "C-IV-1548"
+#define GAL_SPECLINES_NAME_C_IV_1550 "C-IV-1550"
+#define GAL_SPECLINES_NAME_He_II_1640 "He-II-1640"
+#define GAL_SPECLINES_NAME_O_III_1660 "O-III-1660"
+#define GAL_SPECLINES_NAME_O_III_1666 "O-III-1666"
+#define GAL_SPECLINES_NAME_N_III_1746 "N-III-1746"
+#define GAL_SPECLINES_NAME_N_III_1748 "N-III-1748"
+#define GAL_SPECLINES_NAME_Al_III_1854 "Al-III-1854"
+#define GAL_SPECLINES_NAME_Al_III_1862 "Al-III-1862"
+#define GAL_SPECLINES_NAME_Si_III "Si-III"
+#define GAL_SPECLINES_NAME_C_III_1908 "C-III-1908"
+#define GAL_SPECLINES_NAME_N_II_2142 "N-II-2142"
+#define GAL_SPECLINES_NAME_O_III_2320 "O-III-2320"
+#define GAL_SPECLINES_NAME_C_II_2323 "C-II-2323"
+#define GAL_SPECLINES_NAME_C_II_2324 "C-II-2324"
+#define GAL_SPECLINES_NAME_Fe_XI_2648 "Fe-XI-2648"
+#define GAL_SPECLINES_NAME_He_II_2733 "He-II-2733"
+#define GAL_SPECLINES_NAME_Mg_V_2782 "Mg-V-2782"
+#define GAL_SPECLINES_NAME_Mg_II_2795 "Mg-II-2795"
+#define GAL_SPECLINES_NAME_Mg_II_2802 "Mg-II-2802"
+#define GAL_SPECLINES_NAME_Fe_IV_2829 "Fe-IV-2829"
+#define GAL_SPECLINES_NAME_Fe_IV_2835 "Fe-IV-2835"
+#define GAL_SPECLINES_NAME_Ar_IV_2853 "Ar-IV-2853"
+#define GAL_SPECLINES_NAME_Ar_IV_2868 "Ar-IV-2868"
+#define GAL_SPECLINES_NAME_Mg_V_2928 "Mg-V-2928"
+#define GAL_SPECLINES_NAME_He_I_2945 "He-I-2945"
+#define GAL_SPECLINES_NAME_O_III_3132 "O-III-3132"
+#define GAL_SPECLINES_NAME_He_I_3187 "He-I-3187"
+#define GAL_SPECLINES_NAME_He_II_3203 "He-II-3203"
+#define GAL_SPECLINES_NAME_O_III_3312 "O-III-3312"
+#define GAL_SPECLINES_NAME_Ne_V_3345 "Ne-V-3345"
+#define GAL_SPECLINES_NAME_Ne_V_3425 "Ne-V-3425"
+#define GAL_SPECLINES_NAME_O_III_3444 "O-III-3444"
+#define GAL_SPECLINES_NAME_N_I_3466_4 "N-I-3466-4"
+#define GAL_SPECLINES_NAME_N_I_3466_5 "N-I-3466-5"
+#define GAL_SPECLINES_NAME_He_I_3487 "He-I-3487"
+#define GAL_SPECLINES_NAME_Fe_VII_3586 "Fe-VII-3586"
+#define GAL_SPECLINES_NAME_Fe_VI_3662 "Fe-VI-3662"
+#define GAL_SPECLINES_NAME_H_19 "H-19"
+#define GAL_SPECLINES_NAME_H_18 "H-18"
+#define GAL_SPECLINES_NAME_H_17 "H-17"
+#define GAL_SPECLINES_NAME_H_16 "H-16"
+#define GAL_SPECLINES_NAME_H_15 "H-15"
+#define GAL_SPECLINES_NAME_H_14 "H-14"
+#define GAL_SPECLINES_NAME_O_II_3726 "O-II-3726"
+#define GAL_SPECLINES_NAME_O_II_3728 "O-II-3728"
+#define GAL_SPECLINES_NAME_H_13 "H-13"
+#define GAL_SPECLINES_NAME_H_12 "H-12"
+#define GAL_SPECLINES_NAME_Fe_VII_3758 "Fe-VII-3758"
+#define GAL_SPECLINES_NAME_H_11 "H-11"
+#define GAL_SPECLINES_NAME_H_10 "H-10"
+#define GAL_SPECLINES_NAME_H_9 "H-9"
+#define GAL_SPECLINES_NAME_Fe_V_3839 "Fe-V-3839"
+#define GAL_SPECLINES_NAME_Ne_III_3868 "Ne-III-3868"
+#define GAL_SPECLINES_NAME_He_I_3888 "He-I-3888"
+#define GAL_SPECLINES_NAME_H_8 "H-8"
+#define GAL_SPECLINES_NAME_Fe_V_3891 "Fe-V-3891"
+#define GAL_SPECLINES_NAME_Fe_V_3911 "Fe-V-3911"
+#define GAL_SPECLINES_NAME_Ne_III_3967 "Ne-III-3967"
+#define GAL_SPECLINES_NAME_H_epsilon "H-epsilon"
+#define GAL_SPECLINES_NAME_He_I_4026 "He-I-4026"
+#define GAL_SPECLINES_NAME_S_II_4068 "S-II-4068"
+#define GAL_SPECLINES_NAME_Fe_V_4071 "Fe-V-4071"
+#define GAL_SPECLINES_NAME_S_II_4076 "S-II-4076"
+#define GAL_SPECLINES_NAME_H_delta "H-delta"
+#define GAL_SPECLINES_NAME_He_I_4143 "He-I-4143"
+#define GAL_SPECLINES_NAME_Fe_II_4178 "Fe-II-4178"
+#define GAL_SPECLINES_NAME_Fe_V_4180 "Fe-V-4180"
+#define GAL_SPECLINES_NAME_Fe_II_4233 "Fe-II-4233"
+#define GAL_SPECLINES_NAME_Fe_V_4227 "Fe-V-4227"
+#define GAL_SPECLINES_NAME_Fe_II_4287 "Fe-II-4287"
+#define GAL_SPECLINES_NAME_Fe_II_4304 "Fe-II-4304"
+#define GAL_SPECLINES_NAME_O_II_4317 "O-II-4317"
+#define GAL_SPECLINES_NAME_H_gamma "H-gamma"
+#define GAL_SPECLINES_NAME_O_III_4363 "O-III-4363"
+#define GAL_SPECLINES_NAME_Ar_XIV "Ar-XIV"
+#define GAL_SPECLINES_NAME_O_II_4414 "O-II-4414"
+#define GAL_SPECLINES_NAME_Fe_II_4416 "Fe-II-4416"
+#define GAL_SPECLINES_NAME_Fe_II_4452 "Fe-II-4452"
+#define GAL_SPECLINES_NAME_He_I_4471 "He-I-4471"
+#define GAL_SPECLINES_NAME_Fe_II_4489 "Fe-II-4489"
+#define GAL_SPECLINES_NAME_Fe_II_4491 "Fe-II-4491"
+#define GAL_SPECLINES_NAME_N_III_4510 "N-III-4510"
+#define GAL_SPECLINES_NAME_Fe_II_4522 "Fe-II-4522"
+#define GAL_SPECLINES_NAME_Fe_II_4555 "Fe-II-4555"
+#define GAL_SPECLINES_NAME_Fe_II_4582 "Fe-II-4582"
+#define GAL_SPECLINES_NAME_Fe_II_4583 "Fe-II-4583"
+#define GAL_SPECLINES_NAME_Fe_II_4629 "Fe-II-4629"
+#define GAL_SPECLINES_NAME_N_III_4634 "N-III-4634"
+#define GAL_SPECLINES_NAME_N_III_4640 "N-III-4640"
+#define GAL_SPECLINES_NAME_N_III_4641 "N-III-4641"
+#define GAL_SPECLINES_NAME_C_III_4647 "C-III-4647"
+#define GAL_SPECLINES_NAME_C_III_4650 "C-III-4650"
+#define GAL_SPECLINES_NAME_C_III_5651 "C-III-5651"
+#define GAL_SPECLINES_NAME_Fe_III_4658 "Fe-III-4658"
+#define GAL_SPECLINES_NAME_He_II_4685 "He-II-4685"
+#define GAL_SPECLINES_NAME_Ar_IV_4711 "Ar-IV-4711"
+#define GAL_SPECLINES_NAME_Ar_IV_4740 "Ar-IV-4740"
+#define GAL_SPECLINES_NAME_H_beta "H-beta"
+#define GAL_SPECLINES_NAME_Fe_VII_4893 "Fe-VII-4893"
+#define GAL_SPECLINES_NAME_Fe_IV_4903 "Fe-IV-4903"
+#define GAL_SPECLINES_NAME_Fe_II_4923 "Fe-II-4923"
+#define GAL_SPECLINES_NAME_O_III_4958 "O-III-4958"
+#define GAL_SPECLINES_NAME_O_III_5006 "O-III-5006"
+#define GAL_SPECLINES_NAME_Fe_II_5018 "Fe-II-5018"
+#define GAL_SPECLINES_NAME_Fe_III_5084 "Fe-III-5084"
+#define GAL_SPECLINES_NAME_Fe_VI_5145 "Fe-VI-5145"
+#define GAL_SPECLINES_NAME_Fe_VII_5158 "Fe-VII-5158"
+#define GAL_SPECLINES_NAME_Fe_II_5169 "Fe-II-5169"
+#define GAL_SPECLINES_NAME_Fe_VI_5176 "Fe-VI-5176"
+#define GAL_SPECLINES_NAME_Fe_II_5197 "Fe-II-5197"
+#define GAL_SPECLINES_NAME_N_I_5200 "N-I-5200"
+#define GAL_SPECLINES_NAME_Fe_II_5234 "Fe-II-5234"
+#define GAL_SPECLINES_NAME_Fe_IV_5236 "Fe-IV-5236"
+#define GAL_SPECLINES_NAME_Fe_III_5270 "Fe-III-5270"
+#define GAL_SPECLINES_NAME_Fe_II_5276 "Fe-II-5276"
+#define GAL_SPECLINES_NAME_Fe_VII_5276 "Fe-VII-5276"
+#define GAL_SPECLINES_NAME_Fe_XIV "Fe-XIV"
+#define GAL_SPECLINES_NAME_Ca_V "Ca-V"
+#define GAL_SPECLINES_NAME_Fe_II_5316_6 "Fe-II-5316-6"
+#define GAL_SPECLINES_NAME_Fe_II_5316_7 "Fe-II-5316-7"
+#define GAL_SPECLINES_NAME_Fe_VI_5335 "Fe-VI-5335"
+#define GAL_SPECLINES_NAME_Fe_VI_5424 "Fe-VI-5424"
+#define GAL_SPECLINES_NAME_Cl_III_5517 "Cl-III-5517"
+#define GAL_SPECLINES_NAME_Cl_III_5537 "Cl-III-5537"
+#define GAL_SPECLINES_NAME_Fe_VI_5637 "Fe-VI-5637"
+#define GAL_SPECLINES_NAME_Fe_VI_5677 "Fe-VI-5677"
+#define GAL_SPECLINES_NAME_C_III_5697 "C-III-5697"
+#define GAL_SPECLINES_NAME_Fe_VII_5720 "Fe-VII-5720"
+#define GAL_SPECLINES_NAME_N_II_5754 "N-II-5754"
+#define GAL_SPECLINES_NAME_C_IV_5801 "C-IV-5801"
+#define GAL_SPECLINES_NAME_C_IV_5811 "C-IV-5811"
+#define GAL_SPECLINES_NAME_He_I_5875 "He-I-5875"
+#define GAL_SPECLINES_NAME_O_I_6046 "O-I-6046"
+#define GAL_SPECLINES_NAME_Fe_VII_6087 "Fe-VII-6087"
+#define GAL_SPECLINES_NAME_O_I_6300 "O-I-6300"
+#define GAL_SPECLINES_NAME_S_III_6312 "S-III-6312"
+#define GAL_SPECLINES_NAME_Si_II_6347 "Si-II-6347"
+#define GAL_SPECLINES_NAME_O_I_6363 "O-I-6363"
+#define GAL_SPECLINES_NAME_Fe_II_6369 "Fe-II-6369"
+#define GAL_SPECLINES_NAME_Fe_X "Fe-X"
+#define GAL_SPECLINES_NAME_Fe_II_6516 "Fe-II-6516"
+#define GAL_SPECLINES_NAME_N_II_6548 "N-II-6548"
+#define GAL_SPECLINES_NAME_H_alpha "H-alpha"
+#define GAL_SPECLINES_NAME_N_II_6583 "N-II-6583"
+#define GAL_SPECLINES_NAME_S_II_6716 "S-II-6716"
+#define GAL_SPECLINES_NAME_S_II_6730 "S-II-6730"
+#define GAL_SPECLINES_NAME_O_I_7002 "O-I-7002"
+#define GAL_SPECLINES_NAME_Ar_V "Ar-V"
+#define GAL_SPECLINES_NAME_He_I_7065 "He-I-7065"
+#define GAL_SPECLINES_NAME_Ar_III_7135 "Ar-III-7135"
+#define GAL_SPECLINES_NAME_Fe_II_7155 "Fe-II-7155"
+#define GAL_SPECLINES_NAME_Ar_IV_7170 "Ar-IV-7170"
+#define GAL_SPECLINES_NAME_Fe_II_7172 "Fe-II-7172"
+#define GAL_SPECLINES_NAME_C_II_7236 "C-II-7236"
+#define GAL_SPECLINES_NAME_Ar_IV_7237 "Ar-IV-7237"
+#define GAL_SPECLINES_NAME_O_I_7254 "O-I-7254"
+#define GAL_SPECLINES_NAME_Ar_IV_7262 "Ar-IV-7262"
+#define GAL_SPECLINES_NAME_He_I_7281 "He-I-7281"
+#define GAL_SPECLINES_NAME_O_II_7319 "O-II-7319"
+#define GAL_SPECLINES_NAME_O_II_7330 "O-II-7330"
+#define GAL_SPECLINES_NAME_Ni_II_7377 "Ni-II-7377"
+#define GAL_SPECLINES_NAME_Ni_II_7411 "Ni-II-7411"
+#define GAL_SPECLINES_NAME_Fe_II_7452 "Fe-II-7452"
+#define GAL_SPECLINES_NAME_N_I_7468 "N-I-7468"
+#define GAL_SPECLINES_NAME_S_XII "S-XII"
+#define GAL_SPECLINES_NAME_Ar_III_7751 "Ar-III-7751"
+#define GAL_SPECLINES_NAME_He_I_7816 "He-I-7816"
+#define GAL_SPECLINES_NAME_Ar_I_7868 "Ar-I-7868"
+#define GAL_SPECLINES_NAME_Ni_III "Ni-III"
+#define GAL_SPECLINES_NAME_Fe_XI_7891 "Fe-XI-7891"
+#define GAL_SPECLINES_NAME_He_II_8236 "He-II-8236"
+#define GAL_SPECLINES_NAME_Pa_20 "Pa-20"
+#define GAL_SPECLINES_NAME_Pa_19 "Pa-19"
+#define GAL_SPECLINES_NAME_Pa_18 "Pa-18"
+#define GAL_SPECLINES_NAME_O_I_8446 "O-I-8446"
+#define GAL_SPECLINES_NAME_Pa_17 "Pa-17"
+#define GAL_SPECLINES_NAME_Ca_II_8498 "Ca-II-8498"
+#define GAL_SPECLINES_NAME_Pa_16 "Pa-16"
+#define GAL_SPECLINES_NAME_Ca_II_8542 "Ca-II-8542"
+#define GAL_SPECLINES_NAME_Pa_15 "Pa-15"
+#define GAL_SPECLINES_NAME_Cl_II "Cl-II"
+#define GAL_SPECLINES_NAME_Pa_14 "Pa-14"
+#define GAL_SPECLINES_NAME_Fe_II_8616 "Fe-II-8616"
+#define GAL_SPECLINES_NAME_Ca_II_8662 "Ca-II-8662"
+#define GAL_SPECLINES_NAME_Pa_13 "Pa-13"
+#define GAL_SPECLINES_NAME_N_I_8680 "N-I-8680"
+#define GAL_SPECLINES_NAME_N_I_8703 "N-I-8703"
+#define GAL_SPECLINES_NAME_N_I_8711 "N-I-8711"
+#define GAL_SPECLINES_NAME_Pa_12 "Pa-12"
+#define GAL_SPECLINES_NAME_Pa_11 "Pa-11"
+#define GAL_SPECLINES_NAME_Fe_II_8891 "Fe-II-8891"
+#define GAL_SPECLINES_NAME_Pa_10 "Pa-10"
+#define GAL_SPECLINES_NAME_S_III_9068 "S-III-9068"
+#define GAL_SPECLINES_NAME_Pa_9 "Pa-9"
+#define GAL_SPECLINES_NAME_S_III_9531 "S-III-9531"
+#define GAL_SPECLINES_NAME_Pa_epsilon "Pa-epsilon"
+#define GAL_SPECLINES_NAME_C_I_9824 "C-I-9824"
+#define GAL_SPECLINES_NAME_C_I_9850 "C-I-9850"
+#define GAL_SPECLINES_NAME_S_VIII "S-VIII"
+#define GAL_SPECLINES_NAME_He_I_10027 "He-I-10027"
+#define GAL_SPECLINES_NAME_He_I_10031 "He-I-10031"
+#define GAL_SPECLINES_NAME_Pa_delta "Pa-delta"
+#define GAL_SPECLINES_NAME_S_II_10286 "S-II-10286"
+#define GAL_SPECLINES_NAME_S_II_10320 "S-II-10320"
+#define GAL_SPECLINES_NAME_S_II_10336 "S-II-10336"
+#define GAL_SPECLINES_NAME_Fe_XIII "Fe-XIII"
+#define GAL_SPECLINES_NAME_He_I_10830 "He-I-10830"
+#define GAL_SPECLINES_NAME_Pa_gamma "Pa-gamma"
+
+/* The limits. */
+#define GAL_SPECLINES_NAME_LIMIT_LYMAN "Ly-limit"
+#define GAL_SPECLINES_NAME_LIMIT_BALMER "H-limit"
+#define GAL_SPECLINES_NAME_LIMIT_PASCHEN "Pa-limit"
+
+
/*********************************************************************/
/************* Internal names and codes ***************/
/*********************************************************************/
diff --git a/lib/list.c b/lib/list.c
index 50b38061..0ee1b533 100644
--- a/lib/list.c
+++ b/lib/list.c
@@ -227,7 +227,7 @@ gal_list_str_extract(char *string)
char *
-gal_list_str_cat(gal_list_str_t *list)
+gal_list_str_cat(gal_list_str_t *list, char delimiter)
{
size_t bsize=0;
char *c, *o, *out;
@@ -242,7 +242,8 @@ gal_list_str_cat(gal_list_str_t *list)
{
/* Count the characters. If we have a SPACE, we need to add an extra
count for the back slash.*/
- c=tmp->v; do {++bsize; if(*c==' ') ++bsize;} while(*(++c)!='\0');
+ c=tmp->v;
+ do {++bsize; if(*c==delimiter) ++bsize;} while(*(++c)!='\0');
++bsize; /* For the extra space between characters */
}
@@ -253,8 +254,8 @@ gal_list_str_cat(gal_list_str_t *list)
for(tmp=list; tmp!=NULL; tmp=tmp->next)
{
c=tmp->v;
- do {if(*c==' ') *o++='\\'; *o++=*c;} while(*(++c)!='\0');
- *o++=' ';
+ do {if(*c==delimiter) *o++='\\'; *o++=*c;} while(*(++c)!='\0');
+ if(tmp->next) *o++=delimiter;
}
*o='\0';
diff --git a/lib/makeplugin.c b/lib/makeplugin.c
index c2ae1754..19b43d1d 100644
--- a/lib/makeplugin.c
+++ b/lib/makeplugin.c
@@ -126,7 +126,7 @@ makeplugin_text_contains_base(char **argv, int has1_not0)
/* Write the list into one string, but first reverse it so it has the
same order as the input. */
gal_list_str_reverse(&outlist);
- out=gal_list_str_cat(outlist);
+ out=gal_list_str_cat(outlist, ' ');
/* Clean up and return. */
gal_list_str_free(strings, 1);
@@ -243,7 +243,7 @@ makeplugin_fits_with_keyvalue(const char *caller, unsigned
int argc,
outlist=gal_fits_with_keyvalue(files, hdu, name, values);
/* Write the output string */
- out=gal_list_str_cat(outlist);
+ out=gal_list_str_cat(outlist, ' ');
/* Clean up and return. */
gal_list_str_free(files, 1);
@@ -279,7 +279,7 @@ makeplugin_fits_unique_keyvalues(const char *caller,
unsigned int argc,
outlist=gal_fits_unique_keyvalues(files, hdu, name);
/* Write the output value. */
- out=gal_list_str_cat(outlist);
+ out=gal_list_str_cat(outlist, ' ');
/* Clean up and return. */
gal_list_str_free(files, 1);
diff --git a/lib/options.c b/lib/options.c
index ad361c63..426444fe 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -966,7 +966,8 @@ gal_options_parse_list_of_numbers(char *string, char
*filename,
#define OPTIONS_COMMENTED_COMMA 14
#define OPTIONS_COMMENTED_COLON 15
gal_data_t *
-gal_options_parse_list_of_strings(char *string, char *filename, size_t lineno)
+gal_options_parse_list_of_strings(char *string, char *filename,
+ size_t lineno)
{
size_t num;
gal_data_t *out;
@@ -1048,28 +1049,60 @@ gal_options_parse_list_of_strings(char *string, char
*filename, size_t lineno)
-/* The input to this function is a string of any number of strings
- separated by a comma (',') for example: 'a,abc,abcd'. The output
- 'gal_data_t' contains the array of given strings. You can read the
- number of inputs from its 'size' element. */
-gal_data_t *
-gal_options_parse_csv_strings_raw(char *string, char *filename,
- size_t lineno)
+static int
+options_string_has_space(char *string)
{
- size_t i, num;
- gal_data_t *out;
- char *c=string, *cc, *str=NULL;
- gal_list_str_t *list=NULL, *tstrll=NULL;
+ char *c;
+ /* If a space character is present, just return. */
+ for(c=string;*c!='\0';++c) if(*c==' ' || *c=='\t') return 1;
- /* The nature of the arrays/numbers read here is very small, so since
- 'p->cp.minmapsize' might not have been read yet, we will set it to -1
- (largest size_t number), so the values are kept in memory. */
- int quietmmap=1;
- size_t minmapsize=-1;
+ /* If control reaches here, there was no space character. */
+ return 0;
+}
+
+
+
+
+#if 0
+static char *
+options_print_liststr_as_csv(void *inval)
+{
+ char *out=NULL;
+ gal_list_str_t *tmp, *values=*(gal_list_str_t **)(option->value);
+
+ for(tmp=values;tmp!=NULL;tmp=tmp->next)
+ printf("%s: %s\n", __func__, tmp->v);
+
+ /* Return output. */
+ return out;
+}
+#endif
+
+
+
+
+
+/* NOTE: output is REVERSED (since the option parsing automatically
+ reverses STRLLs at its end).. */
+gal_list_str_t *
+gal_options_parse_csv_strings_to_list(char *string, char *filename,
+ size_t lineno)
+{
+ char *str=NULL;
+ char *cc, *c=string;
+ gal_list_str_t *list=NULL;
+ /* Remove any possibly commented new-line where we have a backslash
+ followed by a new-line character (replace the two characters with two
+ single space characters). This can happen with the "--column='arith'"
+ feature in Table, when it gets long (bug #58371). But to be general in
+ other cases too, we'll just correct it here. */
+ for(c=string;*c!='\0';++c)
+ if(*c=='\\' && *(c+1)=='\n') { *c=' '; *(++c)=' '; }
/* Go through the input character by character. */
+ c=string;
while(string && *c!='\0')
{
switch(*c)
@@ -1077,7 +1110,7 @@ gal_options_parse_csv_strings_raw(char *string, char
*filename,
/* Comma marks the transition to the next string. */
case ',':
- /* The whole can't start with a comma. */
+ /* The whole string can't start with a comma. */
if(str==NULL)
{
if(filename)
@@ -1112,11 +1145,80 @@ gal_options_parse_csv_strings_raw(char *string, char
*filename,
++c;
}
-
/* If the last element wasn't a comma, the last string hasn't been added
to the list yet. */
if(str) gal_list_str_add(&list, str, 1);
+ /* Return the reversed list (the option parsing tools automatically
+ reverse STRLLs at the end). */
+ return list;
+}
+
+
+
+
+
+/* For options that can take multiple values multiple times:
+
+ --option=val1,val2 --option=val3,val4,val5 ...
+
+ We want to merge/append all the separate values into separate tokens of
+ a single 'gal_list_str_t'.
+ */
+void *
+gal_options_parse_csv_strings_append(struct argp_option *option, char *arg,
+ char *filename, size_t lineno,
+ void *junk)
+{
+ gal_list_str_t *olist, *alist;
+
+ /* We want to print the values. */
+ if(lineno==-1)
+ return gal_list_str_cat(*(gal_list_str_t **)(option->value), ',');
+
+ /* We want to read the values. */
+ else
+ {
+ /* Read all the values given to this instance of the option. */
+ alist=gal_options_parse_csv_strings_to_list(arg, filename, lineno);
+
+ /* Get the output list and update it by putting the new list before
+ it (note that the option parsing infrastructure will automatically
+ reverse STRLLs. */
+ olist=*(gal_list_str_t **)(option->value);
+ gal_list_str_last(alist)->next=olist;
+ *(gal_list_str_t **)(option->value)=alist;
+
+ /* Return a NULL pointer */
+ return NULL;
+ }
+}
+
+
+
+
+
+/* The input to this function is a string of any number of strings
+ separated by a comma (',') for example: 'a,abc,abcd'. The output
+ 'gal_data_t' contains the array of given strings. You can read the
+ number of inputs from its 'size' element. */
+gal_data_t *
+gal_options_parse_csv_strings_to_data(char *string, char *filename,
+ size_t lineno)
+{
+ size_t i, num;
+ gal_data_t *out;
+ gal_list_str_t *list=NULL, *tstrll=NULL;
+
+
+ /* The nature of the arrays/numbers read here is very small, so since
+ 'p->cp.minmapsize' might not have been read yet, we will set it to -1
+ (largest size_t number), so the values are kept in memory. */
+ int quietmmap=1;
+ size_t minmapsize=-1;
+
+ /* Extract the separate tokens in the CSV string. */
+ list=gal_options_parse_csv_strings_to_list(string, filename, lineno);
/* Allocate the output data structure and fill it up. */
if(list)
@@ -1160,7 +1262,7 @@ gal_options_parse_csv_strings(struct argp_option *option,
char *arg,
char *filename, size_t lineno, void *junk)
{
size_t nc;
- char *c, **strarr;
+ char **strarr;
int i, has_space=0;
gal_data_t *values;
char *str, sstr[GAL_OPTIONS_STATIC_MEM_FOR_VALUES];
@@ -1174,22 +1276,13 @@ gal_options_parse_csv_strings(struct argp_option
*option, char *arg,
/* See if there are any space characters in the final string. */
strarr=values->array;
for(i=0;i<values->size;++i)
- if(has_space==0)
- {
- for(c=strarr[i];*c!='\0';++c)
- if(*c==' ' || *c=='\t')
- {
- has_space=1;
- break;
- }
- }
+ if(has_space==0) has_space=options_string_has_space(strarr[i]);
/* If there is a space, the string must start wth quotation marks. */
nc = has_space ? 1 : 0;
if(has_space) {sstr[0]='"'; sstr[1]='\0';}
-
- /* Write each string into the output string */
+ /* Write each string into the output string. */
for(i=0;i<values->size;++i)
{
if( nc > GAL_OPTIONS_STATIC_MEM_FOR_VALUES-100 )
@@ -1224,9 +1317,11 @@ gal_options_parse_csv_strings(struct argp_option
*option, char *arg,
"given to '--%s'", option->name);
/* Read the values. */
- values=gal_options_parse_csv_strings_raw(arg, filename, lineno);
+ values=gal_options_parse_csv_strings_to_data(arg, filename, lineno);
- /* Put the values into the option. */
+ /* Put the values into the option and return NULL (the return value
+ is only for cases where the user wants to see the values, not set
+ them). */
*(gal_data_t **)(option->value) = values;
return NULL;
}
@@ -1265,7 +1360,7 @@ gal_options_merge_list_of_csv(gal_list_str_t **list)
/* Read the different comma-separated strings into an array (within a
'gal_data_t'). */
- strs=gal_options_parse_csv_strings_raw(tmp->v, NULL, 0);
+ strs=gal_options_parse_csv_strings_to_data(tmp->v, NULL, 0);
strarr=strs->array;
/* Go through all the items and add the pointers to the output
@@ -2609,8 +2704,8 @@ options_parse_file(char *filename, struct
gal_options_common_params *cp,
if( options_set_from_name(name, arg, cp->coptions, cp,
filename, lineno) )
error_at_line(EXIT_FAILURE, 0, filename, lineno,
- "unrecognized option '%s', for the full list of "
- "options, please run with '--help'", name);
+ "unrecognized option '%s', for the full list "
+ "of options, please run with '--help'", name);
}
}
diff --git a/lib/permutation.c b/lib/permutation.c
index a9bc1b65..0115692d 100644
--- a/lib/permutation.c
+++ b/lib/permutation.c
@@ -23,6 +23,8 @@ along with Gnuastro. If not, see
<http://www.gnu.org/licenses/>.
#include <config.h>
#include <stdio.h>
+#include <errno.h>
+#include <error.h>
#include <string.h>
#include <stdlib.h>
@@ -208,3 +210,118 @@ gal_permutation_apply(gal_data_t *input, size_t
*permutation)
void
gal_permutation_apply_onlydim0(gal_data_t *input, size_t *permutation)
{ permutation_apply_raw(input, permutation, 1); }
+
+
+
+
+
+/* Transpose square (2d) input. */
+static void
+permutation_transpose_2d_square(gal_data_t *input)
+{
+ void *a, *b, *swap;
+ size_t width=input->dsize[0];
+ size_t i, j, nbytes=gal_type_sizeof(input->type);
+
+ /* Allocate the SWAP space, we are just allocating an 64-bit integer for
+ its storage. */
+ swap=gal_pointer_allocate(GAL_TYPE_UINT64, 1, 0, __func__, "swap");
+
+ /* Go over the elements. */
+ for(i=0;i<width;++i)
+ for(j=i+1;j<width;++j)
+ {
+ /* For easy reading. */
+ a=gal_pointer_increment(input->array, i*width+j, input->type);
+ b=gal_pointer_increment(input->array, j*width+i, input->type);
+
+ /* Copy the "to" value into the swap, then copy the "from" value
+ into "to" and finally copy swap into "from". */
+ memcpy(swap, a, nbytes);
+ memcpy(a, b, nbytes);
+ memcpy(b, swap, nbytes);
+ }
+
+ /* Clean up. */
+ free(swap);
+}
+
+
+
+
+
+/* Transpose square (2d) input. */
+static void
+permutation_transpose_2d_rectangle(gal_data_t *input)
+{
+ void *a, *b;
+ size_t i, j, nbytes;
+ gal_data_t *out=NULL;
+ size_t *id=input->dsize, od[2]={id[1], id[0]};
+
+ /* Moving values in memory is only necessary when the 0-th dimension has
+ more than one element. */
+ if(input->dsize[0]>1)
+ {
+ /* Allocate the output array. */
+ out=gal_data_alloc(NULL, input->type, 2, od, NULL, 0,
+ input->minmapsize, input->quietmmap,
+ NULL, NULL, NULL);
+
+ /* Go over the elements and put them in the proper place of the
+ output. */
+ nbytes=gal_type_sizeof(input->type);
+ for(i=0;i<id[0];++i)
+ for(j=0;j<id[1];++j)
+ {
+ /* For easy reading. */
+ a=gal_pointer_increment(input->array, i*id[1]+j, input->type);
+ b=gal_pointer_increment(out->array, j*od[1]+i, input->type);
+
+ /* Copy the input ('a' pointer) to output ('b') pointer. */
+ memcpy(b, a, nbytes);
+ }
+
+ /* Free the original input pointer and replace it with the output
+ array, then free the output. */
+ free(input->array);
+ input->array=out->array;
+ out->array=NULL;
+ gal_data_free(out);
+ }
+
+ /* Update the dimesions */
+ input->dsize[0]=od[0];
+ input->dsize[1]=od[1];
+}
+
+
+
+
+
+/* Transpose a 2D dataset. */
+void
+gal_permutation_transpose_2d(gal_data_t *input)
+{
+ uint8_t type;
+ size_t nbytes;
+
+ /* Sanity checks, see the comment below. */
+ type=input->type;
+ nbytes=gal_type_sizeof(type);
+ if(nbytes>8)
+ error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at '%s' to "
+ "find the cause and fix this problem. This function currently "
+ "assumes the largest possible type size is 8 bytes, but the "
+ "requested '%s' type needs %zu bytes", __func__,
+ PACKAGE_BUGREPORT, gal_type_name(type, 1), nbytes);
+ if(input->ndim!=2)
+ error(EXIT_FAILURE, 0, "%s: only 2D inputs are supported", __func__);
+
+ /* A square array can be transposed much more easier and faster than a
+ non-square array. */
+ if(input->dsize[0]==input->dsize[1])
+ permutation_transpose_2d_square(input);
+ else
+ permutation_transpose_2d_rectangle(input);
+}
diff --git a/lib/speclines.c b/lib/speclines.c
index 6fca0955..151f2d7d 100644
--- a/lib/speclines.c
+++ b/lib/speclines.c
@@ -41,49 +41,246 @@ gal_speclines_line_name(int linecode)
{
switch(linecode)
{
- case GAL_SPECLINES_SIIRED: return GAL_SPECLINES_NAME_SIIRED;
- case GAL_SPECLINES_SII: return GAL_SPECLINES_NAME_SII;
- case GAL_SPECLINES_SIIBLUE: return GAL_SPECLINES_NAME_SIIBLUE;
- case GAL_SPECLINES_NIIRED: return GAL_SPECLINES_NAME_NIIRED;
- case GAL_SPECLINES_NII: return GAL_SPECLINES_NAME_NII;
- case GAL_SPECLINES_HALPHA: return GAL_SPECLINES_NAME_HALPHA;
- case GAL_SPECLINES_NIIBLUE: return GAL_SPECLINES_NAME_NIIBLUE;
- case GAL_SPECLINES_OIIIRED_VIS: return GAL_SPECLINES_NAME_OIIIRED_VIS;
- case GAL_SPECLINES_OIII_VIS: return GAL_SPECLINES_NAME_OIII_VIS;
- case GAL_SPECLINES_OIIIBLUE_VIS: return
GAL_SPECLINES_NAME_OIIIBLUE_VIS;
- case GAL_SPECLINES_HBETA: return GAL_SPECLINES_NAME_HBETA;
- case GAL_SPECLINES_HEII_VIS: return GAL_SPECLINES_NAME_HEII_VIS;
- case GAL_SPECLINES_HGAMMA: return GAL_SPECLINES_NAME_HGAMMA;
- case GAL_SPECLINES_HDELTA: return GAL_SPECLINES_NAME_HDELTA;
- case GAL_SPECLINES_HEPSILON: return GAL_SPECLINES_NAME_HEPSILON;
- case GAL_SPECLINES_NEIII: return GAL_SPECLINES_NAME_NEIII;
- case GAL_SPECLINES_OIIRED: return GAL_SPECLINES_NAME_OIIRED;
- case GAL_SPECLINES_OII: return GAL_SPECLINES_NAME_OII;
- case GAL_SPECLINES_OIIBLUE: return GAL_SPECLINES_NAME_OIIBLUE;
- case GAL_SPECLINES_BLIMIT: return GAL_SPECLINES_NAME_BLIMIT;
- case GAL_SPECLINES_MGIIRED: return GAL_SPECLINES_NAME_MGIIRED;
- case GAL_SPECLINES_MGII: return GAL_SPECLINES_NAME_MGII;
- case GAL_SPECLINES_MGIIBLUE: return GAL_SPECLINES_NAME_MGIIBLUE;
- case GAL_SPECLINES_CIIIRED: return GAL_SPECLINES_NAME_CIIIRED;
- case GAL_SPECLINES_CIII: return GAL_SPECLINES_NAME_CIII;
- case GAL_SPECLINES_CIIIBLUE: return GAL_SPECLINES_NAME_CIIIBLUE;
- case GAL_SPECLINES_SiIIIRED: return GAL_SPECLINES_NAME_SiIIIRED;
- case GAL_SPECLINES_SiIII: return GAL_SPECLINES_NAME_SiIII;
- case GAL_SPECLINES_SiIIIBLUE: return GAL_SPECLINES_NAME_SiIIIBLUE;
- case GAL_SPECLINES_OIIIRED_UV: return GAL_SPECLINES_NAME_OIIIRED_UV;
- case GAL_SPECLINES_OIII_UV: return GAL_SPECLINES_NAME_OIII_UV;
- case GAL_SPECLINES_OIIIBLUE_UV: return GAL_SPECLINES_NAME_OIIIBLUE_UV;
- case GAL_SPECLINES_HEII_UV: return GAL_SPECLINES_NAME_HEII_UV;
- case GAL_SPECLINES_CIVRED: return GAL_SPECLINES_NAME_CIVRED;
- case GAL_SPECLINES_CIV: return GAL_SPECLINES_NAME_CIV;
- case GAL_SPECLINES_CIVBLUE: return GAL_SPECLINES_NAME_CIVBLUE;
- case GAL_SPECLINES_NV: return GAL_SPECLINES_NAME_NV;
- case GAL_SPECLINES_LYALPHA: return GAL_SPECLINES_NAME_LYALPHA;
- case GAL_SPECLINES_LYBETA: return GAL_SPECLINES_NAME_LYBETA;
- case GAL_SPECLINES_LYGAMMA: return GAL_SPECLINES_NAME_LYGAMMA;
- case GAL_SPECLINES_LYDELTA: return GAL_SPECLINES_NAME_LYDELTA;
- case GAL_SPECLINES_LYEPSILON: return GAL_SPECLINES_NAME_LYEPSILON;
- case GAL_SPECLINES_LYLIMIT: return GAL_SPECLINES_NAME_LYLIMIT;
+ case GAL_SPECLINES_Ne_VIII_770: return GAL_SPECLINES_NAME_Ne_VIII_770;
+ case GAL_SPECLINES_Ne_VIII_780: return GAL_SPECLINES_NAME_Ne_VIII_780;
+ case GAL_SPECLINES_Ly_epsilon: return GAL_SPECLINES_NAME_Ly_epsilon;
+ case GAL_SPECLINES_Ly_delta: return GAL_SPECLINES_NAME_Ly_delta;
+ case GAL_SPECLINES_Ly_gamma: return GAL_SPECLINES_NAME_Ly_gamma;
+ case GAL_SPECLINES_C_III_977: return GAL_SPECLINES_NAME_C_III_977;
+ case GAL_SPECLINES_N_III_989: return GAL_SPECLINES_NAME_N_III_989;
+ case GAL_SPECLINES_N_III_991_51: return GAL_SPECLINES_NAME_N_III_991_51;
+ case GAL_SPECLINES_N_III_991_57: return GAL_SPECLINES_NAME_N_III_991_57;
+ case GAL_SPECLINES_Ly_beta: return GAL_SPECLINES_NAME_Ly_beta;
+ case GAL_SPECLINES_O_VI_1031: return GAL_SPECLINES_NAME_O_VI_1031;
+ case GAL_SPECLINES_O_VI_1037: return GAL_SPECLINES_NAME_O_VI_1037;
+ case GAL_SPECLINES_Ar_I_1066: return GAL_SPECLINES_NAME_Ar_I_1066;
+ case GAL_SPECLINES_Ly_alpha: return GAL_SPECLINES_NAME_Ly_alpha;
+ case GAL_SPECLINES_N_V_1238: return GAL_SPECLINES_NAME_N_V_1238;
+ case GAL_SPECLINES_N_V_1242: return GAL_SPECLINES_NAME_N_V_1242;
+ case GAL_SPECLINES_Si_II_1260: return GAL_SPECLINES_NAME_Si_II_1260;
+ case GAL_SPECLINES_Si_II_1264: return GAL_SPECLINES_NAME_Si_II_1264;
+ case GAL_SPECLINES_O_I_1302: return GAL_SPECLINES_NAME_O_I_1302;
+ case GAL_SPECLINES_C_II_1334: return GAL_SPECLINES_NAME_C_II_1334;
+ case GAL_SPECLINES_C_II_1335: return GAL_SPECLINES_NAME_C_II_1335;
+ case GAL_SPECLINES_Si_IV_1393: return GAL_SPECLINES_NAME_Si_IV_1393;
+ case GAL_SPECLINES_O_IV_1397: return GAL_SPECLINES_NAME_O_IV_1397;
+ case GAL_SPECLINES_O_IV_1399: return GAL_SPECLINES_NAME_O_IV_1399;
+ case GAL_SPECLINES_Si_IV_1402: return GAL_SPECLINES_NAME_Si_IV_1402;
+ case GAL_SPECLINES_N_IV_1486: return GAL_SPECLINES_NAME_N_IV_1486;
+ case GAL_SPECLINES_C_IV_1548: return GAL_SPECLINES_NAME_C_IV_1548;
+ case GAL_SPECLINES_C_IV_1550: return GAL_SPECLINES_NAME_C_IV_1550;
+ case GAL_SPECLINES_He_II_1640: return GAL_SPECLINES_NAME_He_II_1640;
+ case GAL_SPECLINES_O_III_1660: return GAL_SPECLINES_NAME_O_III_1660;
+ case GAL_SPECLINES_O_III_1666: return GAL_SPECLINES_NAME_O_III_1666;
+ case GAL_SPECLINES_N_III_1746: return GAL_SPECLINES_NAME_N_III_1746;
+ case GAL_SPECLINES_N_III_1748: return GAL_SPECLINES_NAME_N_III_1748;
+ case GAL_SPECLINES_Al_III_1854: return GAL_SPECLINES_NAME_Al_III_1854;
+ case GAL_SPECLINES_Al_III_1862: return GAL_SPECLINES_NAME_Al_III_1862;
+ case GAL_SPECLINES_Si_III: return GAL_SPECLINES_NAME_Si_III;
+ case GAL_SPECLINES_C_III_1908: return GAL_SPECLINES_NAME_C_III_1908;
+ case GAL_SPECLINES_N_II_2142: return GAL_SPECLINES_NAME_N_II_2142;
+ case GAL_SPECLINES_O_III_2320: return GAL_SPECLINES_NAME_O_III_2320;
+ case GAL_SPECLINES_C_II_2323: return GAL_SPECLINES_NAME_C_II_2323;
+ case GAL_SPECLINES_C_II_2324: return GAL_SPECLINES_NAME_C_II_2324;
+ case GAL_SPECLINES_Fe_XI_2648: return GAL_SPECLINES_NAME_Fe_XI_2648;
+ case GAL_SPECLINES_He_II_2733: return GAL_SPECLINES_NAME_He_II_2733;
+ case GAL_SPECLINES_Mg_V_2782: return GAL_SPECLINES_NAME_Mg_V_2782;
+ case GAL_SPECLINES_Mg_II_2795: return GAL_SPECLINES_NAME_Mg_II_2795;
+ case GAL_SPECLINES_Mg_II_2802: return GAL_SPECLINES_NAME_Mg_II_2802;
+ case GAL_SPECLINES_Fe_IV_2829: return GAL_SPECLINES_NAME_Fe_IV_2829;
+ case GAL_SPECLINES_Fe_IV_2835: return GAL_SPECLINES_NAME_Fe_IV_2835;
+ case GAL_SPECLINES_Ar_IV_2853: return GAL_SPECLINES_NAME_Ar_IV_2853;
+ case GAL_SPECLINES_Ar_IV_2868: return GAL_SPECLINES_NAME_Ar_IV_2868;
+ case GAL_SPECLINES_Mg_V_2928: return GAL_SPECLINES_NAME_Mg_V_2928;
+ case GAL_SPECLINES_He_I_2945: return GAL_SPECLINES_NAME_He_I_2945;
+ case GAL_SPECLINES_O_III_3132: return GAL_SPECLINES_NAME_O_III_3132;
+ case GAL_SPECLINES_He_I_3187: return GAL_SPECLINES_NAME_He_I_3187;
+ case GAL_SPECLINES_He_II_3203: return GAL_SPECLINES_NAME_He_II_3203;
+ case GAL_SPECLINES_O_III_3312: return GAL_SPECLINES_NAME_O_III_3312;
+ case GAL_SPECLINES_Ne_V_3345: return GAL_SPECLINES_NAME_Ne_V_3345;
+ case GAL_SPECLINES_Ne_V_3425: return GAL_SPECLINES_NAME_Ne_V_3425;
+ case GAL_SPECLINES_O_III_3444: return GAL_SPECLINES_NAME_O_III_3444;
+ case GAL_SPECLINES_N_I_3466_4: return GAL_SPECLINES_NAME_N_I_3466_4;
+ case GAL_SPECLINES_N_I_3466_5: return GAL_SPECLINES_NAME_N_I_3466_5;
+ case GAL_SPECLINES_He_I_3487: return GAL_SPECLINES_NAME_He_I_3487;
+ case GAL_SPECLINES_Fe_VII_3586: return GAL_SPECLINES_NAME_Fe_VII_3586;
+ case GAL_SPECLINES_Fe_VI_3662: return GAL_SPECLINES_NAME_Fe_VI_3662;
+ case GAL_SPECLINES_H_19: return GAL_SPECLINES_NAME_H_19;
+ case GAL_SPECLINES_H_18: return GAL_SPECLINES_NAME_H_18;
+ case GAL_SPECLINES_H_17: return GAL_SPECLINES_NAME_H_17;
+ case GAL_SPECLINES_H_16: return GAL_SPECLINES_NAME_H_16;
+ case GAL_SPECLINES_H_15: return GAL_SPECLINES_NAME_H_15;
+ case GAL_SPECLINES_H_14: return GAL_SPECLINES_NAME_H_14;
+ case GAL_SPECLINES_O_II_3726: return GAL_SPECLINES_NAME_O_II_3726;
+ case GAL_SPECLINES_O_II_3728: return GAL_SPECLINES_NAME_O_II_3728;
+ case GAL_SPECLINES_H_13: return GAL_SPECLINES_NAME_H_13;
+ case GAL_SPECLINES_H_12: return GAL_SPECLINES_NAME_H_12;
+ case GAL_SPECLINES_Fe_VII_3758: return GAL_SPECLINES_NAME_Fe_VII_3758;
+ case GAL_SPECLINES_H_11: return GAL_SPECLINES_NAME_H_11;
+ case GAL_SPECLINES_H_10: return GAL_SPECLINES_NAME_H_10;
+ case GAL_SPECLINES_H_9: return GAL_SPECLINES_NAME_H_9;
+ case GAL_SPECLINES_Fe_V_3839: return GAL_SPECLINES_NAME_Fe_V_3839;
+ case GAL_SPECLINES_Ne_III_3868: return GAL_SPECLINES_NAME_Ne_III_3868;
+ case GAL_SPECLINES_He_I_3888: return GAL_SPECLINES_NAME_He_I_3888;
+ case GAL_SPECLINES_H_8: return GAL_SPECLINES_NAME_H_8;
+ case GAL_SPECLINES_Fe_V_3891: return GAL_SPECLINES_NAME_Fe_V_3891;
+ case GAL_SPECLINES_Fe_V_3911: return GAL_SPECLINES_NAME_Fe_V_3911;
+ case GAL_SPECLINES_Ne_III_3967: return GAL_SPECLINES_NAME_Ne_III_3967;
+ case GAL_SPECLINES_H_epsilon: return GAL_SPECLINES_NAME_H_epsilon;
+ case GAL_SPECLINES_He_I_4026: return GAL_SPECLINES_NAME_He_I_4026;
+ case GAL_SPECLINES_S_II_4068: return GAL_SPECLINES_NAME_S_II_4068;
+ case GAL_SPECLINES_Fe_V_4071: return GAL_SPECLINES_NAME_Fe_V_4071;
+ case GAL_SPECLINES_S_II_4076: return GAL_SPECLINES_NAME_S_II_4076;
+ case GAL_SPECLINES_H_delta: return GAL_SPECLINES_NAME_H_delta;
+ case GAL_SPECLINES_He_I_4143: return GAL_SPECLINES_NAME_He_I_4143;
+ case GAL_SPECLINES_Fe_II_4178: return GAL_SPECLINES_NAME_Fe_II_4178;
+ case GAL_SPECLINES_Fe_V_4180: return GAL_SPECLINES_NAME_Fe_V_4180;
+ case GAL_SPECLINES_Fe_II_4233: return GAL_SPECLINES_NAME_Fe_II_4233;
+ case GAL_SPECLINES_Fe_V_4227: return GAL_SPECLINES_NAME_Fe_V_4227;
+ case GAL_SPECLINES_Fe_II_4287: return GAL_SPECLINES_NAME_Fe_II_4287;
+ case GAL_SPECLINES_Fe_II_4304: return GAL_SPECLINES_NAME_Fe_II_4304;
+ case GAL_SPECLINES_O_II_4317: return GAL_SPECLINES_NAME_O_II_4317;
+ case GAL_SPECLINES_H_gamma: return GAL_SPECLINES_NAME_H_gamma;
+ case GAL_SPECLINES_O_III_4363: return GAL_SPECLINES_NAME_O_III_4363;
+ case GAL_SPECLINES_Ar_XIV: return GAL_SPECLINES_NAME_Ar_XIV;
+ case GAL_SPECLINES_O_II_4414: return GAL_SPECLINES_NAME_O_II_4414;
+ case GAL_SPECLINES_Fe_II_4416: return GAL_SPECLINES_NAME_Fe_II_4416;
+ case GAL_SPECLINES_Fe_II_4452: return GAL_SPECLINES_NAME_Fe_II_4452;
+ case GAL_SPECLINES_He_I_4471: return GAL_SPECLINES_NAME_He_I_4471;
+ case GAL_SPECLINES_Fe_II_4489: return GAL_SPECLINES_NAME_Fe_II_4489;
+ case GAL_SPECLINES_Fe_II_4491: return GAL_SPECLINES_NAME_Fe_II_4491;
+ case GAL_SPECLINES_N_III_4510: return GAL_SPECLINES_NAME_N_III_4510;
+ case GAL_SPECLINES_Fe_II_4522: return GAL_SPECLINES_NAME_Fe_II_4522;
+ case GAL_SPECLINES_Fe_II_4555: return GAL_SPECLINES_NAME_Fe_II_4555;
+ case GAL_SPECLINES_Fe_II_4582: return GAL_SPECLINES_NAME_Fe_II_4582;
+ case GAL_SPECLINES_Fe_II_4583: return GAL_SPECLINES_NAME_Fe_II_4583;
+ case GAL_SPECLINES_Fe_II_4629: return GAL_SPECLINES_NAME_Fe_II_4629;
+ case GAL_SPECLINES_N_III_4634: return GAL_SPECLINES_NAME_N_III_4634;
+ case GAL_SPECLINES_N_III_4640: return GAL_SPECLINES_NAME_N_III_4640;
+ case GAL_SPECLINES_N_III_4641: return GAL_SPECLINES_NAME_N_III_4641;
+ case GAL_SPECLINES_C_III_4647: return GAL_SPECLINES_NAME_C_III_4647;
+ case GAL_SPECLINES_C_III_4650: return GAL_SPECLINES_NAME_C_III_4650;
+ case GAL_SPECLINES_C_III_5651: return GAL_SPECLINES_NAME_C_III_5651;
+ case GAL_SPECLINES_Fe_III_4658: return GAL_SPECLINES_NAME_Fe_III_4658;
+ case GAL_SPECLINES_He_II_4685: return GAL_SPECLINES_NAME_He_II_4685;
+ case GAL_SPECLINES_Ar_IV_4711: return GAL_SPECLINES_NAME_Ar_IV_4711;
+ case GAL_SPECLINES_Ar_IV_4740: return GAL_SPECLINES_NAME_Ar_IV_4740;
+ case GAL_SPECLINES_H_beta: return GAL_SPECLINES_NAME_H_beta;
+ case GAL_SPECLINES_Fe_VII_4893: return GAL_SPECLINES_NAME_Fe_VII_4893;
+ case GAL_SPECLINES_Fe_IV_4903: return GAL_SPECLINES_NAME_Fe_IV_4903;
+ case GAL_SPECLINES_Fe_II_4923: return GAL_SPECLINES_NAME_Fe_II_4923;
+ case GAL_SPECLINES_O_III_4958: return GAL_SPECLINES_NAME_O_III_4958;
+ case GAL_SPECLINES_O_III_5006: return GAL_SPECLINES_NAME_O_III_5006;
+ case GAL_SPECLINES_Fe_II_5018: return GAL_SPECLINES_NAME_Fe_II_5018;
+ case GAL_SPECLINES_Fe_III_5084: return GAL_SPECLINES_NAME_Fe_III_5084;
+ case GAL_SPECLINES_Fe_VI_5145: return GAL_SPECLINES_NAME_Fe_VI_5145;
+ case GAL_SPECLINES_Fe_VII_5158: return GAL_SPECLINES_NAME_Fe_VII_5158;
+ case GAL_SPECLINES_Fe_II_5169: return GAL_SPECLINES_NAME_Fe_II_5169;
+ case GAL_SPECLINES_Fe_VI_5176: return GAL_SPECLINES_NAME_Fe_VI_5176;
+ case GAL_SPECLINES_Fe_II_5197: return GAL_SPECLINES_NAME_Fe_II_5197;
+ case GAL_SPECLINES_N_I_5200: return GAL_SPECLINES_NAME_N_I_5200;
+ case GAL_SPECLINES_Fe_II_5234: return GAL_SPECLINES_NAME_Fe_II_5234;
+ case GAL_SPECLINES_Fe_IV_5236: return GAL_SPECLINES_NAME_Fe_IV_5236;
+ case GAL_SPECLINES_Fe_III_5270: return GAL_SPECLINES_NAME_Fe_III_5270;
+ case GAL_SPECLINES_Fe_II_5276: return GAL_SPECLINES_NAME_Fe_II_5276;
+ case GAL_SPECLINES_Fe_VII_5276: return GAL_SPECLINES_NAME_Fe_VII_5276;
+ case GAL_SPECLINES_Fe_XIV: return GAL_SPECLINES_NAME_Fe_XIV;
+ case GAL_SPECLINES_Ca_V: return GAL_SPECLINES_NAME_Ca_V;
+ case GAL_SPECLINES_Fe_II_5316_6: return GAL_SPECLINES_NAME_Fe_II_5316_6;
+ case GAL_SPECLINES_Fe_II_5316_7: return GAL_SPECLINES_NAME_Fe_II_5316_7;
+ case GAL_SPECLINES_Fe_VI_5335: return GAL_SPECLINES_NAME_Fe_VI_5335;
+ case GAL_SPECLINES_Fe_VI_5424: return GAL_SPECLINES_NAME_Fe_VI_5424;
+ case GAL_SPECLINES_Cl_III_5517: return GAL_SPECLINES_NAME_Cl_III_5517;
+ case GAL_SPECLINES_Cl_III_5537: return GAL_SPECLINES_NAME_Cl_III_5537;
+ case GAL_SPECLINES_Fe_VI_5637: return GAL_SPECLINES_NAME_Fe_VI_5637;
+ case GAL_SPECLINES_Fe_VI_5677: return GAL_SPECLINES_NAME_Fe_VI_5677;
+ case GAL_SPECLINES_C_III_5697: return GAL_SPECLINES_NAME_C_III_5697;
+ case GAL_SPECLINES_Fe_VII_5720: return GAL_SPECLINES_NAME_Fe_VII_5720;
+ case GAL_SPECLINES_N_II_5754: return GAL_SPECLINES_NAME_N_II_5754;
+ case GAL_SPECLINES_C_IV_5801: return GAL_SPECLINES_NAME_C_IV_5801;
+ case GAL_SPECLINES_C_IV_5811: return GAL_SPECLINES_NAME_C_IV_5811;
+ case GAL_SPECLINES_He_I_5875: return GAL_SPECLINES_NAME_He_I_5875;
+ case GAL_SPECLINES_O_I_6046: return GAL_SPECLINES_NAME_O_I_6046;
+ case GAL_SPECLINES_Fe_VII_6087: return GAL_SPECLINES_NAME_Fe_VII_6087;
+ case GAL_SPECLINES_O_I_6300: return GAL_SPECLINES_NAME_O_I_6300;
+ case GAL_SPECLINES_S_III_6312: return GAL_SPECLINES_NAME_S_III_6312;
+ case GAL_SPECLINES_Si_II_6347: return GAL_SPECLINES_NAME_Si_II_6347;
+ case GAL_SPECLINES_O_I_6363: return GAL_SPECLINES_NAME_O_I_6363;
+ case GAL_SPECLINES_Fe_II_6369: return GAL_SPECLINES_NAME_Fe_II_6369;
+ case GAL_SPECLINES_Fe_X: return GAL_SPECLINES_NAME_Fe_X;
+ case GAL_SPECLINES_Fe_II_6516: return GAL_SPECLINES_NAME_Fe_II_6516;
+ case GAL_SPECLINES_N_II_6548: return GAL_SPECLINES_NAME_N_II_6548;
+ case GAL_SPECLINES_H_alpha: return GAL_SPECLINES_NAME_H_alpha;
+ case GAL_SPECLINES_N_II_6583: return GAL_SPECLINES_NAME_N_II_6583;
+ case GAL_SPECLINES_S_II_6716: return GAL_SPECLINES_NAME_S_II_6716;
+ case GAL_SPECLINES_S_II_6730: return GAL_SPECLINES_NAME_S_II_6730;
+ case GAL_SPECLINES_O_I_7002: return GAL_SPECLINES_NAME_O_I_7002;
+ case GAL_SPECLINES_Ar_V: return GAL_SPECLINES_NAME_Ar_V;
+ case GAL_SPECLINES_He_I_7065: return GAL_SPECLINES_NAME_He_I_7065;
+ case GAL_SPECLINES_Ar_III_7135: return GAL_SPECLINES_NAME_Ar_III_7135;
+ case GAL_SPECLINES_Fe_II_7155: return GAL_SPECLINES_NAME_Fe_II_7155;
+ case GAL_SPECLINES_Ar_IV_7170: return GAL_SPECLINES_NAME_Ar_IV_7170;
+ case GAL_SPECLINES_Fe_II_7172: return GAL_SPECLINES_NAME_Fe_II_7172;
+ case GAL_SPECLINES_C_II_7236: return GAL_SPECLINES_NAME_C_II_7236;
+ case GAL_SPECLINES_Ar_IV_7237: return GAL_SPECLINES_NAME_Ar_IV_7237;
+ case GAL_SPECLINES_O_I_7254: return GAL_SPECLINES_NAME_O_I_7254;
+ case GAL_SPECLINES_Ar_IV_7262: return GAL_SPECLINES_NAME_Ar_IV_7262;
+ case GAL_SPECLINES_He_I_7281: return GAL_SPECLINES_NAME_He_I_7281;
+ case GAL_SPECLINES_O_II_7319: return GAL_SPECLINES_NAME_O_II_7319;
+ case GAL_SPECLINES_O_II_7330: return GAL_SPECLINES_NAME_O_II_7330;
+ case GAL_SPECLINES_Ni_II_7377: return GAL_SPECLINES_NAME_Ni_II_7377;
+ case GAL_SPECLINES_Ni_II_7411: return GAL_SPECLINES_NAME_Ni_II_7411;
+ case GAL_SPECLINES_Fe_II_7452: return GAL_SPECLINES_NAME_Fe_II_7452;
+ case GAL_SPECLINES_N_I_7468: return GAL_SPECLINES_NAME_N_I_7468;
+ case GAL_SPECLINES_S_XII: return GAL_SPECLINES_NAME_S_XII;
+ case GAL_SPECLINES_Ar_III_7751: return GAL_SPECLINES_NAME_Ar_III_7751;
+ case GAL_SPECLINES_He_I_7816: return GAL_SPECLINES_NAME_He_I_7816;
+ case GAL_SPECLINES_Ar_I_7868: return GAL_SPECLINES_NAME_Ar_I_7868;
+ case GAL_SPECLINES_Ni_III: return GAL_SPECLINES_NAME_Ni_III;
+ case GAL_SPECLINES_Fe_XI_7891: return GAL_SPECLINES_NAME_Fe_XI_7891;
+ case GAL_SPECLINES_He_II_8236: return GAL_SPECLINES_NAME_He_II_8236;
+ case GAL_SPECLINES_Pa_20: return GAL_SPECLINES_NAME_Pa_20;
+ case GAL_SPECLINES_Pa_19: return GAL_SPECLINES_NAME_Pa_19;
+ case GAL_SPECLINES_Pa_18: return GAL_SPECLINES_NAME_Pa_18;
+ case GAL_SPECLINES_O_I_8446: return GAL_SPECLINES_NAME_O_I_8446;
+ case GAL_SPECLINES_Pa_17: return GAL_SPECLINES_NAME_Pa_17;
+ case GAL_SPECLINES_Ca_II_8498: return GAL_SPECLINES_NAME_Ca_II_8498;
+ case GAL_SPECLINES_Pa_16: return GAL_SPECLINES_NAME_Pa_16;
+ case GAL_SPECLINES_Ca_II_8542: return GAL_SPECLINES_NAME_Ca_II_8542;
+ case GAL_SPECLINES_Pa_15: return GAL_SPECLINES_NAME_Pa_15;
+ case GAL_SPECLINES_Cl_II: return GAL_SPECLINES_NAME_Cl_II;
+ case GAL_SPECLINES_Pa_14: return GAL_SPECLINES_NAME_Pa_14;
+ case GAL_SPECLINES_Fe_II_8616: return GAL_SPECLINES_NAME_Fe_II_8616;
+ case GAL_SPECLINES_Ca_II_8662: return GAL_SPECLINES_NAME_Ca_II_8662;
+ case GAL_SPECLINES_Pa_13: return GAL_SPECLINES_NAME_Pa_13;
+ case GAL_SPECLINES_N_I_8680: return GAL_SPECLINES_NAME_N_I_8680;
+ case GAL_SPECLINES_N_I_8703: return GAL_SPECLINES_NAME_N_I_8703;
+ case GAL_SPECLINES_N_I_8711: return GAL_SPECLINES_NAME_N_I_8711;
+ case GAL_SPECLINES_Pa_12: return GAL_SPECLINES_NAME_Pa_12;
+ case GAL_SPECLINES_Pa_11: return GAL_SPECLINES_NAME_Pa_11;
+ case GAL_SPECLINES_Fe_II_8891: return GAL_SPECLINES_NAME_Fe_II_8891;
+ case GAL_SPECLINES_Pa_10: return GAL_SPECLINES_NAME_Pa_10;
+ case GAL_SPECLINES_S_III_9068: return GAL_SPECLINES_NAME_S_III_9068;
+ case GAL_SPECLINES_Pa_9: return GAL_SPECLINES_NAME_Pa_9;
+ case GAL_SPECLINES_S_III_9531: return GAL_SPECLINES_NAME_S_III_9531;
+ case GAL_SPECLINES_Pa_epsilon: return GAL_SPECLINES_NAME_Pa_epsilon;
+ case GAL_SPECLINES_C_I_9824: return GAL_SPECLINES_NAME_C_I_9824;
+ case GAL_SPECLINES_C_I_9850: return GAL_SPECLINES_NAME_C_I_9850;
+ case GAL_SPECLINES_S_VIII: return GAL_SPECLINES_NAME_S_VIII;
+ case GAL_SPECLINES_He_I_10027: return GAL_SPECLINES_NAME_He_I_10027;
+ case GAL_SPECLINES_He_I_10031: return GAL_SPECLINES_NAME_He_I_10031;
+ case GAL_SPECLINES_Pa_delta: return GAL_SPECLINES_NAME_Pa_delta;
+ case GAL_SPECLINES_S_II_10286: return GAL_SPECLINES_NAME_S_II_10286;
+ case GAL_SPECLINES_S_II_10320: return GAL_SPECLINES_NAME_S_II_10320;
+ case GAL_SPECLINES_S_II_10336: return GAL_SPECLINES_NAME_S_II_10336;
+ case GAL_SPECLINES_Fe_XIII: return GAL_SPECLINES_NAME_Fe_XIII;
+ case GAL_SPECLINES_He_I_10830: return GAL_SPECLINES_NAME_He_I_10830;
+ case GAL_SPECLINES_Pa_gamma: return GAL_SPECLINES_NAME_Pa_gamma;
+
+ /* Limits */
+ case GAL_SPECLINES_LIMIT_LYMAN: return GAL_SPECLINES_NAME_LIMIT_LYMAN;
+ case GAL_SPECLINES_LIMIT_BALMER: return GAL_SPECLINES_NAME_LIMIT_BALMER;
+ case GAL_SPECLINES_LIMIT_PASCHEN: return GAL_SPECLINES_NAME_LIMIT_PASCHEN;
default: return NULL;
}
return NULL;
@@ -97,92 +294,486 @@ gal_speclines_line_name(int linecode)
int
gal_speclines_line_code(char *name)
{
- if( !strcmp(name, GAL_SPECLINES_NAME_SIIRED) )
- return GAL_SPECLINES_SIIRED;
- else if( !strcmp(name, GAL_SPECLINES_NAME_SII) )
- return GAL_SPECLINES_SII;
- else if( !strcmp(name, GAL_SPECLINES_NAME_SIIBLUE) )
- return GAL_SPECLINES_SIIBLUE;
- if( !strcmp(name, GAL_SPECLINES_NAME_NIIRED) )
- return GAL_SPECLINES_NIIRED;
- else if( !strcmp(name, GAL_SPECLINES_NAME_NII) )
- return GAL_SPECLINES_NII;
- else if( !strcmp(name, GAL_SPECLINES_NAME_HALPHA) )
- return GAL_SPECLINES_HALPHA;
- else if( !strcmp(name, GAL_SPECLINES_NAME_NIIBLUE) )
- return GAL_SPECLINES_NIIBLUE;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OIIIRED_VIS) )
- return GAL_SPECLINES_OIIIRED_VIS;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OIII_VIS) )
- return GAL_SPECLINES_OIII_VIS;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OIIIBLUE_VIS) )
- return GAL_SPECLINES_OIIIBLUE_VIS;
- else if( !strcmp(name, GAL_SPECLINES_NAME_HBETA) )
- return GAL_SPECLINES_HBETA;
- else if( !strcmp(name, GAL_SPECLINES_NAME_HEII_VIS) )
- return GAL_SPECLINES_HEII_VIS;
- else if( !strcmp(name, GAL_SPECLINES_NAME_HGAMMA) )
- return GAL_SPECLINES_HGAMMA;
- else if( !strcmp(name, GAL_SPECLINES_NAME_HDELTA) )
- return GAL_SPECLINES_HDELTA;
- else if( !strcmp(name, GAL_SPECLINES_NAME_HEPSILON) )
- return GAL_SPECLINES_HEPSILON;
- else if( !strcmp(name, GAL_SPECLINES_NAME_NEIII) )
- return GAL_SPECLINES_NEIII;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OIIRED) )
- return GAL_SPECLINES_OIIRED;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OII) )
- return GAL_SPECLINES_OII;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OIIBLUE) )
- return GAL_SPECLINES_OIIBLUE;
- else if( !strcmp(name, GAL_SPECLINES_NAME_BLIMIT) )
- return GAL_SPECLINES_BLIMIT;
- else if( !strcmp(name, GAL_SPECLINES_NAME_MGIIRED) )
- return GAL_SPECLINES_MGIIRED;
- else if( !strcmp(name, GAL_SPECLINES_NAME_MGII) )
- return GAL_SPECLINES_MGII;
- else if( !strcmp(name, GAL_SPECLINES_NAME_MGIIBLUE) )
- return GAL_SPECLINES_MGIIBLUE;
- else if( !strcmp(name, GAL_SPECLINES_NAME_CIIIRED) )
- return GAL_SPECLINES_CIIIRED;
- else if( !strcmp(name, GAL_SPECLINES_NAME_CIII) )
- return GAL_SPECLINES_CIII;
- else if( !strcmp(name, GAL_SPECLINES_NAME_CIIIBLUE) )
- return GAL_SPECLINES_CIIIBLUE;
- else if( !strcmp(name, GAL_SPECLINES_NAME_SiIIIRED) )
- return GAL_SPECLINES_SiIIIRED;
- else if( !strcmp(name, GAL_SPECLINES_NAME_SiIII) )
- return GAL_SPECLINES_SiIII;
- else if( !strcmp(name, GAL_SPECLINES_NAME_SiIIIBLUE) )
- return GAL_SPECLINES_SiIIIBLUE;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OIIIRED_UV) )
- return GAL_SPECLINES_OIIIRED_UV;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OIII_UV) )
- return GAL_SPECLINES_OIII_UV;
- else if( !strcmp(name, GAL_SPECLINES_NAME_OIIIBLUE_UV) )
- return GAL_SPECLINES_OIIIBLUE_UV;
- else if( !strcmp(name, GAL_SPECLINES_NAME_HEII_UV) )
- return GAL_SPECLINES_HEII_UV;
- else if( !strcmp(name, GAL_SPECLINES_NAME_CIVRED) )
- return GAL_SPECLINES_CIVRED;
- else if( !strcmp(name, GAL_SPECLINES_NAME_CIV) )
- return GAL_SPECLINES_CIV;
- else if( !strcmp(name, GAL_SPECLINES_NAME_CIVBLUE) )
- return GAL_SPECLINES_CIVBLUE;
- else if( !strcmp(name, GAL_SPECLINES_NAME_NV) )
- return GAL_SPECLINES_NV;
- else if( !strcmp(name, GAL_SPECLINES_NAME_LYALPHA) )
- return GAL_SPECLINES_LYALPHA;
- else if( !strcmp(name, GAL_SPECLINES_NAME_LYBETA) )
- return GAL_SPECLINES_LYBETA;
- else if( !strcmp(name, GAL_SPECLINES_NAME_LYGAMMA) )
- return GAL_SPECLINES_LYGAMMA;
- else if( !strcmp(name, GAL_SPECLINES_NAME_LYDELTA) )
- return GAL_SPECLINES_LYDELTA;
- else if( !strcmp(name, GAL_SPECLINES_NAME_LYEPSILON) )
- return GAL_SPECLINES_LYEPSILON;
- else if( !strcmp(name, GAL_SPECLINES_NAME_LYLIMIT) )
- return GAL_SPECLINES_LYLIMIT;
+ if( !strcmp(name, GAL_SPECLINES_NAME_Ne_VIII_770) )
+ return GAL_SPECLINES_Ne_VIII_770;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ne_VIII_780) )
+ return GAL_SPECLINES_Ne_VIII_780;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ly_epsilon) )
+ return GAL_SPECLINES_Ly_epsilon;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ly_delta) )
+ return GAL_SPECLINES_Ly_delta;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ly_gamma) )
+ return GAL_SPECLINES_Ly_gamma;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_III_977) )
+ return GAL_SPECLINES_C_III_977;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_989) )
+ return GAL_SPECLINES_N_III_989;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_991_51) )
+ return GAL_SPECLINES_N_III_991_51;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_991_57) )
+ return GAL_SPECLINES_N_III_991_57;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ly_beta) )
+ return GAL_SPECLINES_Ly_beta;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_VI_1031) )
+ return GAL_SPECLINES_O_VI_1031;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_VI_1037) )
+ return GAL_SPECLINES_O_VI_1037;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_I_1066) )
+ return GAL_SPECLINES_Ar_I_1066;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ly_alpha) )
+ return GAL_SPECLINES_Ly_alpha;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_V_1238) )
+ return GAL_SPECLINES_N_V_1238;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_V_1242) )
+ return GAL_SPECLINES_N_V_1242;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Si_II_1260) )
+ return GAL_SPECLINES_Si_II_1260;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Si_II_1264) )
+ return GAL_SPECLINES_Si_II_1264;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_I_1302) )
+ return GAL_SPECLINES_O_I_1302;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_II_1334) )
+ return GAL_SPECLINES_C_II_1334;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_II_1335) )
+ return GAL_SPECLINES_C_II_1335;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Si_IV_1393) )
+ return GAL_SPECLINES_Si_IV_1393;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_IV_1397) )
+ return GAL_SPECLINES_O_IV_1397;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_IV_1399) )
+ return GAL_SPECLINES_O_IV_1399;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Si_IV_1402) )
+ return GAL_SPECLINES_Si_IV_1402;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_IV_1486) )
+ return GAL_SPECLINES_N_IV_1486;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_IV_1548) )
+ return GAL_SPECLINES_C_IV_1548;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_IV_1550) )
+ return GAL_SPECLINES_C_IV_1550;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_II_1640) )
+ return GAL_SPECLINES_He_II_1640;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_1660) )
+ return GAL_SPECLINES_O_III_1660;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_1666) )
+ return GAL_SPECLINES_O_III_1666;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_1746) )
+ return GAL_SPECLINES_N_III_1746;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_1748) )
+ return GAL_SPECLINES_N_III_1748;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Al_III_1854) )
+ return GAL_SPECLINES_Al_III_1854;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Al_III_1862) )
+ return GAL_SPECLINES_Al_III_1862;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Si_III) )
+ return GAL_SPECLINES_Si_III;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_III_1908) )
+ return GAL_SPECLINES_C_III_1908;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_II_2142) )
+ return GAL_SPECLINES_N_II_2142;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_2320) )
+ return GAL_SPECLINES_O_III_2320;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_II_2323) )
+ return GAL_SPECLINES_C_II_2323;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_II_2324) )
+ return GAL_SPECLINES_C_II_2324;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_XI_2648) )
+ return GAL_SPECLINES_Fe_XI_2648;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_II_2733) )
+ return GAL_SPECLINES_He_II_2733;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Mg_V_2782) )
+ return GAL_SPECLINES_Mg_V_2782;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Mg_II_2795) )
+ return GAL_SPECLINES_Mg_II_2795;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Mg_II_2802) )
+ return GAL_SPECLINES_Mg_II_2802;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_IV_2829) )
+ return GAL_SPECLINES_Fe_IV_2829;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_IV_2835) )
+ return GAL_SPECLINES_Fe_IV_2835;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_IV_2853) )
+ return GAL_SPECLINES_Ar_IV_2853;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_IV_2868) )
+ return GAL_SPECLINES_Ar_IV_2868;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Mg_V_2928) )
+ return GAL_SPECLINES_Mg_V_2928;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_2945) )
+ return GAL_SPECLINES_He_I_2945;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_3132) )
+ return GAL_SPECLINES_O_III_3132;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_3187) )
+ return GAL_SPECLINES_He_I_3187;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_II_3203) )
+ return GAL_SPECLINES_He_II_3203;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_3312) )
+ return GAL_SPECLINES_O_III_3312;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ne_V_3345) )
+ return GAL_SPECLINES_Ne_V_3345;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ne_V_3425) )
+ return GAL_SPECLINES_Ne_V_3425;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_3444) )
+ return GAL_SPECLINES_O_III_3444;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_I_3466_4) )
+ return GAL_SPECLINES_N_I_3466_4;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_I_3466_5) )
+ return GAL_SPECLINES_N_I_3466_5;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_3487) )
+ return GAL_SPECLINES_He_I_3487;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VII_3586) )
+ return GAL_SPECLINES_Fe_VII_3586;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VI_3662) )
+ return GAL_SPECLINES_Fe_VI_3662;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_19) )
+ return GAL_SPECLINES_H_19;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_18) )
+ return GAL_SPECLINES_H_18;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_17) )
+ return GAL_SPECLINES_H_17;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_16) )
+ return GAL_SPECLINES_H_16;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_15) )
+ return GAL_SPECLINES_H_15;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_14) )
+ return GAL_SPECLINES_H_14;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_II_3726) )
+ return GAL_SPECLINES_O_II_3726;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_II_3728) )
+ return GAL_SPECLINES_O_II_3728;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_13) )
+ return GAL_SPECLINES_H_13;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_12) )
+ return GAL_SPECLINES_H_12;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VII_3758) )
+ return GAL_SPECLINES_Fe_VII_3758;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_11) )
+ return GAL_SPECLINES_H_11;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_10) )
+ return GAL_SPECLINES_H_10;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_9) )
+ return GAL_SPECLINES_H_9;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_V_3839) )
+ return GAL_SPECLINES_Fe_V_3839;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ne_III_3868) )
+ return GAL_SPECLINES_Ne_III_3868;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_3888) )
+ return GAL_SPECLINES_He_I_3888;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_8) )
+ return GAL_SPECLINES_H_8;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_V_3891) )
+ return GAL_SPECLINES_Fe_V_3891;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_V_3911) )
+ return GAL_SPECLINES_Fe_V_3911;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ne_III_3967) )
+ return GAL_SPECLINES_Ne_III_3967;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_epsilon) )
+ return GAL_SPECLINES_H_epsilon;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_4026) )
+ return GAL_SPECLINES_He_I_4026;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_II_4068) )
+ return GAL_SPECLINES_S_II_4068;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_V_4071) )
+ return GAL_SPECLINES_Fe_V_4071;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_II_4076) )
+ return GAL_SPECLINES_S_II_4076;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_delta) )
+ return GAL_SPECLINES_H_delta;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_4143) )
+ return GAL_SPECLINES_He_I_4143;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4178) )
+ return GAL_SPECLINES_Fe_II_4178;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_V_4180) )
+ return GAL_SPECLINES_Fe_V_4180;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4233) )
+ return GAL_SPECLINES_Fe_II_4233;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_V_4227) )
+ return GAL_SPECLINES_Fe_V_4227;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4287) )
+ return GAL_SPECLINES_Fe_II_4287;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4304) )
+ return GAL_SPECLINES_Fe_II_4304;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_II_4317) )
+ return GAL_SPECLINES_O_II_4317;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_gamma) )
+ return GAL_SPECLINES_H_gamma;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_4363) )
+ return GAL_SPECLINES_O_III_4363;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_XIV) )
+ return GAL_SPECLINES_Ar_XIV;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_II_4414) )
+ return GAL_SPECLINES_O_II_4414;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4416) )
+ return GAL_SPECLINES_Fe_II_4416;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4452) )
+ return GAL_SPECLINES_Fe_II_4452;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_4471) )
+ return GAL_SPECLINES_He_I_4471;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4489) )
+ return GAL_SPECLINES_Fe_II_4489;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4491) )
+ return GAL_SPECLINES_Fe_II_4491;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_4510) )
+ return GAL_SPECLINES_N_III_4510;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4522) )
+ return GAL_SPECLINES_Fe_II_4522;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4555) )
+ return GAL_SPECLINES_Fe_II_4555;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4582) )
+ return GAL_SPECLINES_Fe_II_4582;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4583) )
+ return GAL_SPECLINES_Fe_II_4583;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4629) )
+ return GAL_SPECLINES_Fe_II_4629;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_4634) )
+ return GAL_SPECLINES_N_III_4634;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_4640) )
+ return GAL_SPECLINES_N_III_4640;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_III_4641) )
+ return GAL_SPECLINES_N_III_4641;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_III_4647) )
+ return GAL_SPECLINES_C_III_4647;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_III_4650) )
+ return GAL_SPECLINES_C_III_4650;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_III_5651) )
+ return GAL_SPECLINES_C_III_5651;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_III_4658) )
+ return GAL_SPECLINES_Fe_III_4658;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_II_4685) )
+ return GAL_SPECLINES_He_II_4685;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_IV_4711) )
+ return GAL_SPECLINES_Ar_IV_4711;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_IV_4740) )
+ return GAL_SPECLINES_Ar_IV_4740;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_beta) )
+ return GAL_SPECLINES_H_beta;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VII_4893) )
+ return GAL_SPECLINES_Fe_VII_4893;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_IV_4903) )
+ return GAL_SPECLINES_Fe_IV_4903;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_4923) )
+ return GAL_SPECLINES_Fe_II_4923;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_4958) )
+ return GAL_SPECLINES_O_III_4958;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_III_5006) )
+ return GAL_SPECLINES_O_III_5006;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_5018) )
+ return GAL_SPECLINES_Fe_II_5018;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_III_5084) )
+ return GAL_SPECLINES_Fe_III_5084;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VI_5145) )
+ return GAL_SPECLINES_Fe_VI_5145;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VII_5158) )
+ return GAL_SPECLINES_Fe_VII_5158;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_5169) )
+ return GAL_SPECLINES_Fe_II_5169;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VI_5176) )
+ return GAL_SPECLINES_Fe_VI_5176;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_5197) )
+ return GAL_SPECLINES_Fe_II_5197;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_I_5200) )
+ return GAL_SPECLINES_N_I_5200;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_5234) )
+ return GAL_SPECLINES_Fe_II_5234;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_IV_5236) )
+ return GAL_SPECLINES_Fe_IV_5236;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_III_5270) )
+ return GAL_SPECLINES_Fe_III_5270;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_5276) )
+ return GAL_SPECLINES_Fe_II_5276;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VII_5276) )
+ return GAL_SPECLINES_Fe_VII_5276;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_XIV) )
+ return GAL_SPECLINES_Fe_XIV;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ca_V) )
+ return GAL_SPECLINES_Ca_V;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_5316_6) )
+ return GAL_SPECLINES_Fe_II_5316_6;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_5316_7) )
+ return GAL_SPECLINES_Fe_II_5316_7;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VI_5335) )
+ return GAL_SPECLINES_Fe_VI_5335;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VI_5424) )
+ return GAL_SPECLINES_Fe_VI_5424;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Cl_III_5517) )
+ return GAL_SPECLINES_Cl_III_5517;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Cl_III_5537) )
+ return GAL_SPECLINES_Cl_III_5537;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VI_5637) )
+ return GAL_SPECLINES_Fe_VI_5637;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VI_5677) )
+ return GAL_SPECLINES_Fe_VI_5677;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_III_5697) )
+ return GAL_SPECLINES_C_III_5697;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VII_5720) )
+ return GAL_SPECLINES_Fe_VII_5720;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_II_5754) )
+ return GAL_SPECLINES_N_II_5754;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_IV_5801) )
+ return GAL_SPECLINES_C_IV_5801;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_IV_5811) )
+ return GAL_SPECLINES_C_IV_5811;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_5875) )
+ return GAL_SPECLINES_He_I_5875;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_I_6046) )
+ return GAL_SPECLINES_O_I_6046;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_VII_6087) )
+ return GAL_SPECLINES_Fe_VII_6087;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_I_6300) )
+ return GAL_SPECLINES_O_I_6300;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_III_6312) )
+ return GAL_SPECLINES_S_III_6312;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Si_II_6347) )
+ return GAL_SPECLINES_Si_II_6347;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_I_6363) )
+ return GAL_SPECLINES_O_I_6363;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_6369) )
+ return GAL_SPECLINES_Fe_II_6369;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_X) )
+ return GAL_SPECLINES_Fe_X;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_6516) )
+ return GAL_SPECLINES_Fe_II_6516;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_II_6548) )
+ return GAL_SPECLINES_N_II_6548;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_H_alpha) )
+ return GAL_SPECLINES_H_alpha;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_II_6583) )
+ return GAL_SPECLINES_N_II_6583;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_II_6716) )
+ return GAL_SPECLINES_S_II_6716;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_II_6730) )
+ return GAL_SPECLINES_S_II_6730;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_I_7002) )
+ return GAL_SPECLINES_O_I_7002;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_V) )
+ return GAL_SPECLINES_Ar_V;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_7065) )
+ return GAL_SPECLINES_He_I_7065;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_III_7135) )
+ return GAL_SPECLINES_Ar_III_7135;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_7155) )
+ return GAL_SPECLINES_Fe_II_7155;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_IV_7170) )
+ return GAL_SPECLINES_Ar_IV_7170;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_7172) )
+ return GAL_SPECLINES_Fe_II_7172;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_II_7236) )
+ return GAL_SPECLINES_C_II_7236;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_IV_7237) )
+ return GAL_SPECLINES_Ar_IV_7237;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_I_7254) )
+ return GAL_SPECLINES_O_I_7254;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_IV_7262) )
+ return GAL_SPECLINES_Ar_IV_7262;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_7281) )
+ return GAL_SPECLINES_He_I_7281;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_II_7319) )
+ return GAL_SPECLINES_O_II_7319;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_II_7330) )
+ return GAL_SPECLINES_O_II_7330;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ni_II_7377) )
+ return GAL_SPECLINES_Ni_II_7377;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ni_II_7411) )
+ return GAL_SPECLINES_Ni_II_7411;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_7452) )
+ return GAL_SPECLINES_Fe_II_7452;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_I_7468) )
+ return GAL_SPECLINES_N_I_7468;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_XII) )
+ return GAL_SPECLINES_S_XII;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_III_7751) )
+ return GAL_SPECLINES_Ar_III_7751;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_7816) )
+ return GAL_SPECLINES_He_I_7816;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ar_I_7868) )
+ return GAL_SPECLINES_Ar_I_7868;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ni_III) )
+ return GAL_SPECLINES_Ni_III;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_XI_7891) )
+ return GAL_SPECLINES_Fe_XI_7891;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_II_8236) )
+ return GAL_SPECLINES_He_II_8236;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_20) )
+ return GAL_SPECLINES_Pa_20;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_19) )
+ return GAL_SPECLINES_Pa_19;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_18) )
+ return GAL_SPECLINES_Pa_18;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_O_I_8446) )
+ return GAL_SPECLINES_O_I_8446;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_17) )
+ return GAL_SPECLINES_Pa_17;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ca_II_8498) )
+ return GAL_SPECLINES_Ca_II_8498;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_16) )
+ return GAL_SPECLINES_Pa_16;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ca_II_8542) )
+ return GAL_SPECLINES_Ca_II_8542;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_15) )
+ return GAL_SPECLINES_Pa_15;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Cl_II) )
+ return GAL_SPECLINES_Cl_II;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_14) )
+ return GAL_SPECLINES_Pa_14;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_8616) )
+ return GAL_SPECLINES_Fe_II_8616;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Ca_II_8662) )
+ return GAL_SPECLINES_Ca_II_8662;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_13) )
+ return GAL_SPECLINES_Pa_13;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_I_8680) )
+ return GAL_SPECLINES_N_I_8680;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_I_8703) )
+ return GAL_SPECLINES_N_I_8703;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_N_I_8711) )
+ return GAL_SPECLINES_N_I_8711;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_12) )
+ return GAL_SPECLINES_Pa_12;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_11) )
+ return GAL_SPECLINES_Pa_11;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_II_8891) )
+ return GAL_SPECLINES_Fe_II_8891;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_10) )
+ return GAL_SPECLINES_Pa_10;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_III_9068) )
+ return GAL_SPECLINES_S_III_9068;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_9) )
+ return GAL_SPECLINES_Pa_9;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_III_9531) )
+ return GAL_SPECLINES_S_III_9531;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_epsilon) )
+ return GAL_SPECLINES_Pa_epsilon;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_I_9824) )
+ return GAL_SPECLINES_C_I_9824;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_C_I_9850) )
+ return GAL_SPECLINES_C_I_9850;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_VIII) )
+ return GAL_SPECLINES_S_VIII;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_10027) )
+ return GAL_SPECLINES_He_I_10027;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_10031) )
+ return GAL_SPECLINES_He_I_10031;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_delta) )
+ return GAL_SPECLINES_Pa_delta;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_II_10286) )
+ return GAL_SPECLINES_S_II_10286;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_II_10320) )
+ return GAL_SPECLINES_S_II_10320;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_S_II_10336) )
+ return GAL_SPECLINES_S_II_10336;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Fe_XIII) )
+ return GAL_SPECLINES_Fe_XIII;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_He_I_10830) )
+ return GAL_SPECLINES_He_I_10830;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_Pa_gamma) )
+ return GAL_SPECLINES_Pa_gamma;
+
+ /* Limits */
+ else if( !strcmp(name, GAL_SPECLINES_NAME_LIMIT_LYMAN) )
+ return GAL_SPECLINES_LIMIT_LYMAN;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_LIMIT_BALMER) )
+ return GAL_SPECLINES_LIMIT_BALMER;
+ else if( !strcmp(name, GAL_SPECLINES_NAME_LIMIT_PASCHEN) )
+ return GAL_SPECLINES_LIMIT_PASCHEN;
+
+ /* Invalid. */
else return GAL_SPECLINES_INVALID;
return GAL_SPECLINES_INVALID;
}
@@ -197,49 +788,247 @@ gal_speclines_line_angstrom(int linecode)
{
switch(linecode)
{
- case GAL_SPECLINES_SIIRED: return GAL_SPECLINES_ANGSTROM_SIIRED;
- case GAL_SPECLINES_SII: return GAL_SPECLINES_ANGSTROM_SII;
- case GAL_SPECLINES_SIIBLUE: return GAL_SPECLINES_ANGSTROM_SIIBLUE;
- case GAL_SPECLINES_NIIRED: return GAL_SPECLINES_ANGSTROM_NIIRED;
- case GAL_SPECLINES_NII: return GAL_SPECLINES_ANGSTROM_NII;
- case GAL_SPECLINES_HALPHA: return GAL_SPECLINES_ANGSTROM_HALPHA;
- case GAL_SPECLINES_NIIBLUE: return GAL_SPECLINES_ANGSTROM_NIIBLUE;
- case GAL_SPECLINES_OIIIRED_VIS: return
GAL_SPECLINES_ANGSTROM_OIIIRED_VIS;
- case GAL_SPECLINES_OIII_VIS: return GAL_SPECLINES_ANGSTROM_OIII_VIS;
- case GAL_SPECLINES_OIIIBLUE_VIS: return
GAL_SPECLINES_ANGSTROM_OIIIBLUE_VIS;
- case GAL_SPECLINES_HBETA: return GAL_SPECLINES_ANGSTROM_HBETA;
- case GAL_SPECLINES_HEII_VIS: return GAL_SPECLINES_ANGSTROM_HEII_VIS;
- case GAL_SPECLINES_HGAMMA: return GAL_SPECLINES_ANGSTROM_HGAMMA;
- case GAL_SPECLINES_HDELTA: return GAL_SPECLINES_ANGSTROM_HDELTA;
- case GAL_SPECLINES_HEPSILON: return GAL_SPECLINES_ANGSTROM_HEPSILON;
- case GAL_SPECLINES_NEIII: return GAL_SPECLINES_ANGSTROM_NEIII;
- case GAL_SPECLINES_OIIRED: return GAL_SPECLINES_ANGSTROM_OIIRED;
- case GAL_SPECLINES_OII: return GAL_SPECLINES_ANGSTROM_OII;
- case GAL_SPECLINES_OIIBLUE: return GAL_SPECLINES_ANGSTROM_OIIBLUE;
- case GAL_SPECLINES_BLIMIT: return GAL_SPECLINES_ANGSTROM_BLIMIT;
- case GAL_SPECLINES_MGIIRED: return GAL_SPECLINES_ANGSTROM_MGIIRED;
- case GAL_SPECLINES_MGII: return GAL_SPECLINES_ANGSTROM_MGII;
- case GAL_SPECLINES_MGIIBLUE: return GAL_SPECLINES_ANGSTROM_MGIIBLUE;
- case GAL_SPECLINES_CIIIRED: return GAL_SPECLINES_ANGSTROM_CIIIRED;
- case GAL_SPECLINES_CIII: return GAL_SPECLINES_ANGSTROM_CIII;
- case GAL_SPECLINES_CIIIBLUE: return GAL_SPECLINES_ANGSTROM_CIIIBLUE;
- case GAL_SPECLINES_SiIIIRED: return GAL_SPECLINES_ANGSTROM_SiIIIRED;
- case GAL_SPECLINES_SiIII: return GAL_SPECLINES_ANGSTROM_SiIII;
- case GAL_SPECLINES_SiIIIBLUE: return GAL_SPECLINES_ANGSTROM_SiIIIBLUE;
- case GAL_SPECLINES_OIIIRED_UV: return GAL_SPECLINES_ANGSTROM_OIIIRED_UV;
- case GAL_SPECLINES_OIII_UV: return GAL_SPECLINES_ANGSTROM_OIII_UV;
- case GAL_SPECLINES_OIIIBLUE_UV: return
GAL_SPECLINES_ANGSTROM_OIIIBLUE_UV;
- case GAL_SPECLINES_HEII_UV: return GAL_SPECLINES_ANGSTROM_HEII_UV;
- case GAL_SPECLINES_CIVRED: return GAL_SPECLINES_ANGSTROM_CIVRED;
- case GAL_SPECLINES_CIV: return GAL_SPECLINES_ANGSTROM_CIV;
- case GAL_SPECLINES_CIVBLUE: return GAL_SPECLINES_ANGSTROM_CIVBLUE;
- case GAL_SPECLINES_NV: return GAL_SPECLINES_ANGSTROM_NV;
- case GAL_SPECLINES_LYALPHA: return GAL_SPECLINES_ANGSTROM_LYALPHA;
- case GAL_SPECLINES_LYBETA: return GAL_SPECLINES_ANGSTROM_LYBETA;
- case GAL_SPECLINES_LYGAMMA: return GAL_SPECLINES_ANGSTROM_LYGAMMA;
- case GAL_SPECLINES_LYDELTA: return GAL_SPECLINES_ANGSTROM_LYDELTA;
- case GAL_SPECLINES_LYEPSILON: return GAL_SPECLINES_ANGSTROM_LYEPSILON;
- case GAL_SPECLINES_LYLIMIT: return GAL_SPECLINES_ANGSTROM_LYLIMIT;
+ case GAL_SPECLINES_Ne_VIII_770: return
GAL_SPECLINES_ANGSTROM_Ne_VIII_770;
+ case GAL_SPECLINES_Ne_VIII_780: return
GAL_SPECLINES_ANGSTROM_Ne_VIII_780;
+ case GAL_SPECLINES_Ly_epsilon: return
GAL_SPECLINES_ANGSTROM_Ly_epsilon;
+ case GAL_SPECLINES_Ly_delta: return GAL_SPECLINES_ANGSTROM_Ly_delta;
+ case GAL_SPECLINES_Ly_gamma: return GAL_SPECLINES_ANGSTROM_Ly_gamma;
+ case GAL_SPECLINES_C_III_977: return GAL_SPECLINES_ANGSTROM_C_III_977;
+ case GAL_SPECLINES_N_III_989: return GAL_SPECLINES_ANGSTROM_N_III_989;
+ case GAL_SPECLINES_N_III_991_51: return
GAL_SPECLINES_ANGSTROM_N_III_991_51;
+ case GAL_SPECLINES_N_III_991_57: return
GAL_SPECLINES_ANGSTROM_N_III_991_57;
+ case GAL_SPECLINES_Ly_beta: return GAL_SPECLINES_ANGSTROM_Ly_beta;
+ case GAL_SPECLINES_O_VI_1031: return GAL_SPECLINES_ANGSTROM_O_VI_1031;
+ case GAL_SPECLINES_O_VI_1037: return GAL_SPECLINES_ANGSTROM_O_VI_1037;
+ case GAL_SPECLINES_Ar_I_1066: return GAL_SPECLINES_ANGSTROM_Ar_I_1066;
+ case GAL_SPECLINES_Ly_alpha: return GAL_SPECLINES_ANGSTROM_Ly_alpha;
+ case GAL_SPECLINES_N_V_1238: return GAL_SPECLINES_ANGSTROM_N_V_1238;
+ case GAL_SPECLINES_N_V_1242: return GAL_SPECLINES_ANGSTROM_N_V_1242;
+ case GAL_SPECLINES_Si_II_1260: return
GAL_SPECLINES_ANGSTROM_Si_II_1260;
+ case GAL_SPECLINES_Si_II_1264: return
GAL_SPECLINES_ANGSTROM_Si_II_1264;
+ case GAL_SPECLINES_O_I_1302: return GAL_SPECLINES_ANGSTROM_O_I_1302;
+ case GAL_SPECLINES_C_II_1334: return GAL_SPECLINES_ANGSTROM_C_II_1334;
+ case GAL_SPECLINES_C_II_1335: return GAL_SPECLINES_ANGSTROM_C_II_1335;
+ case GAL_SPECLINES_Si_IV_1393: return
GAL_SPECLINES_ANGSTROM_Si_IV_1393;
+ case GAL_SPECLINES_O_IV_1397: return GAL_SPECLINES_ANGSTROM_O_IV_1397;
+ case GAL_SPECLINES_O_IV_1399: return GAL_SPECLINES_ANGSTROM_O_IV_1399;
+ case GAL_SPECLINES_Si_IV_1402: return
GAL_SPECLINES_ANGSTROM_Si_IV_1402;
+ case GAL_SPECLINES_N_IV_1486: return GAL_SPECLINES_ANGSTROM_N_IV_1486;
+ case GAL_SPECLINES_C_IV_1548: return GAL_SPECLINES_ANGSTROM_C_IV_1548;
+ case GAL_SPECLINES_C_IV_1550: return GAL_SPECLINES_ANGSTROM_C_IV_1550;
+ case GAL_SPECLINES_He_II_1640: return
GAL_SPECLINES_ANGSTROM_He_II_1640;
+ case GAL_SPECLINES_O_III_1660: return
GAL_SPECLINES_ANGSTROM_O_III_1660;
+ case GAL_SPECLINES_O_III_1666: return
GAL_SPECLINES_ANGSTROM_O_III_1666;
+ case GAL_SPECLINES_N_III_1746: return
GAL_SPECLINES_ANGSTROM_N_III_1746;
+ case GAL_SPECLINES_N_III_1748: return
GAL_SPECLINES_ANGSTROM_N_III_1748;
+ case GAL_SPECLINES_Al_III_1854: return
GAL_SPECLINES_ANGSTROM_Al_III_1854;
+ case GAL_SPECLINES_Al_III_1862: return
GAL_SPECLINES_ANGSTROM_Al_III_1862;
+ case GAL_SPECLINES_Si_III: return GAL_SPECLINES_ANGSTROM_Si_III;
+ case GAL_SPECLINES_C_III_1908: return
GAL_SPECLINES_ANGSTROM_C_III_1908;
+ case GAL_SPECLINES_N_II_2142: return GAL_SPECLINES_ANGSTROM_N_II_2142;
+ case GAL_SPECLINES_O_III_2320: return
GAL_SPECLINES_ANGSTROM_O_III_2320;
+ case GAL_SPECLINES_C_II_2323: return GAL_SPECLINES_ANGSTROM_C_II_2323;
+ case GAL_SPECLINES_C_II_2324: return GAL_SPECLINES_ANGSTROM_C_II_2324;
+ case GAL_SPECLINES_Fe_XI_2648: return
GAL_SPECLINES_ANGSTROM_Fe_XI_2648;
+ case GAL_SPECLINES_He_II_2733: return
GAL_SPECLINES_ANGSTROM_He_II_2733;
+ case GAL_SPECLINES_Mg_V_2782: return GAL_SPECLINES_ANGSTROM_Mg_V_2782;
+ case GAL_SPECLINES_Mg_II_2795: return
GAL_SPECLINES_ANGSTROM_Mg_II_2795;
+ case GAL_SPECLINES_Mg_II_2802: return
GAL_SPECLINES_ANGSTROM_Mg_II_2802;
+ case GAL_SPECLINES_Fe_IV_2829: return
GAL_SPECLINES_ANGSTROM_Fe_IV_2829;
+ case GAL_SPECLINES_Fe_IV_2835: return
GAL_SPECLINES_ANGSTROM_Fe_IV_2835;
+ case GAL_SPECLINES_Ar_IV_2853: return
GAL_SPECLINES_ANGSTROM_Ar_IV_2853;
+ case GAL_SPECLINES_Ar_IV_2868: return
GAL_SPECLINES_ANGSTROM_Ar_IV_2868;
+ case GAL_SPECLINES_Mg_V_2928: return GAL_SPECLINES_ANGSTROM_Mg_V_2928;
+ case GAL_SPECLINES_He_I_2945: return GAL_SPECLINES_ANGSTROM_He_I_2945;
+ case GAL_SPECLINES_O_III_3132: return
GAL_SPECLINES_ANGSTROM_O_III_3132;
+ case GAL_SPECLINES_He_I_3187: return GAL_SPECLINES_ANGSTROM_He_I_3187;
+ case GAL_SPECLINES_He_II_3203: return
GAL_SPECLINES_ANGSTROM_He_II_3203;
+ case GAL_SPECLINES_O_III_3312: return
GAL_SPECLINES_ANGSTROM_O_III_3312;
+ case GAL_SPECLINES_Ne_V_3345: return GAL_SPECLINES_ANGSTROM_Ne_V_3345;
+ case GAL_SPECLINES_Ne_V_3425: return GAL_SPECLINES_ANGSTROM_Ne_V_3425;
+ case GAL_SPECLINES_O_III_3444: return
GAL_SPECLINES_ANGSTROM_O_III_3444;
+ case GAL_SPECLINES_N_I_3466_4: return
GAL_SPECLINES_ANGSTROM_N_I_3466_4;
+ case GAL_SPECLINES_N_I_3466_5: return
GAL_SPECLINES_ANGSTROM_N_I_3466_5;
+ case GAL_SPECLINES_He_I_3487: return GAL_SPECLINES_ANGSTROM_He_I_3487;
+ case GAL_SPECLINES_Fe_VII_3586: return
GAL_SPECLINES_ANGSTROM_Fe_VII_3586;
+ case GAL_SPECLINES_Fe_VI_3662: return
GAL_SPECLINES_ANGSTROM_Fe_VI_3662;
+ case GAL_SPECLINES_H_19: return GAL_SPECLINES_ANGSTROM_H_19;
+ case GAL_SPECLINES_H_18: return GAL_SPECLINES_ANGSTROM_H_18;
+ case GAL_SPECLINES_H_17: return GAL_SPECLINES_ANGSTROM_H_17;
+ case GAL_SPECLINES_H_16: return GAL_SPECLINES_ANGSTROM_H_16;
+ case GAL_SPECLINES_H_15: return GAL_SPECLINES_ANGSTROM_H_15;
+ case GAL_SPECLINES_H_14: return GAL_SPECLINES_ANGSTROM_H_14;
+ case GAL_SPECLINES_O_II_3726: return GAL_SPECLINES_ANGSTROM_O_II_3726;
+ case GAL_SPECLINES_O_II_3728: return GAL_SPECLINES_ANGSTROM_O_II_3728;
+ case GAL_SPECLINES_H_13: return GAL_SPECLINES_ANGSTROM_H_13;
+ case GAL_SPECLINES_H_12: return GAL_SPECLINES_ANGSTROM_H_12;
+ case GAL_SPECLINES_Fe_VII_3758: return
GAL_SPECLINES_ANGSTROM_Fe_VII_3758;
+ case GAL_SPECLINES_H_11: return GAL_SPECLINES_ANGSTROM_H_11;
+ case GAL_SPECLINES_H_10: return GAL_SPECLINES_ANGSTROM_H_10;
+ case GAL_SPECLINES_H_9: return GAL_SPECLINES_ANGSTROM_H_9;
+ case GAL_SPECLINES_Fe_V_3839: return GAL_SPECLINES_ANGSTROM_Fe_V_3839;
+ case GAL_SPECLINES_Ne_III_3868: return
GAL_SPECLINES_ANGSTROM_Ne_III_3868;
+ case GAL_SPECLINES_He_I_3888: return GAL_SPECLINES_ANGSTROM_He_I_3888;
+ case GAL_SPECLINES_H_8: return GAL_SPECLINES_ANGSTROM_H_8;
+ case GAL_SPECLINES_Fe_V_3891: return GAL_SPECLINES_ANGSTROM_Fe_V_3891;
+ case GAL_SPECLINES_Fe_V_3911: return GAL_SPECLINES_ANGSTROM_Fe_V_3911;
+ case GAL_SPECLINES_Ne_III_3967: return
GAL_SPECLINES_ANGSTROM_Ne_III_3967;
+ case GAL_SPECLINES_H_epsilon: return GAL_SPECLINES_ANGSTROM_H_epsilon;
+ case GAL_SPECLINES_He_I_4026: return GAL_SPECLINES_ANGSTROM_He_I_4026;
+ case GAL_SPECLINES_S_II_4068: return GAL_SPECLINES_ANGSTROM_S_II_4068;
+ case GAL_SPECLINES_Fe_V_4071: return GAL_SPECLINES_ANGSTROM_Fe_V_4071;
+ case GAL_SPECLINES_S_II_4076: return GAL_SPECLINES_ANGSTROM_S_II_4076;
+ case GAL_SPECLINES_H_delta: return GAL_SPECLINES_ANGSTROM_H_delta;
+ case GAL_SPECLINES_He_I_4143: return GAL_SPECLINES_ANGSTROM_He_I_4143;
+ case GAL_SPECLINES_Fe_II_4178: return
GAL_SPECLINES_ANGSTROM_Fe_II_4178;
+ case GAL_SPECLINES_Fe_V_4180: return GAL_SPECLINES_ANGSTROM_Fe_V_4180;
+ case GAL_SPECLINES_Fe_II_4233: return
GAL_SPECLINES_ANGSTROM_Fe_II_4233;
+ case GAL_SPECLINES_Fe_V_4227: return GAL_SPECLINES_ANGSTROM_Fe_V_4227;
+ case GAL_SPECLINES_Fe_II_4287: return
GAL_SPECLINES_ANGSTROM_Fe_II_4287;
+ case GAL_SPECLINES_Fe_II_4304: return
GAL_SPECLINES_ANGSTROM_Fe_II_4304;
+ case GAL_SPECLINES_O_II_4317: return GAL_SPECLINES_ANGSTROM_O_II_4317;
+ case GAL_SPECLINES_H_gamma: return GAL_SPECLINES_ANGSTROM_H_gamma;
+ case GAL_SPECLINES_O_III_4363: return
GAL_SPECLINES_ANGSTROM_O_III_4363;
+ case GAL_SPECLINES_Ar_XIV: return GAL_SPECLINES_ANGSTROM_Ar_XIV;
+ case GAL_SPECLINES_O_II_4414: return GAL_SPECLINES_ANGSTROM_O_II_4414;
+ case GAL_SPECLINES_Fe_II_4416: return
GAL_SPECLINES_ANGSTROM_Fe_II_4416;
+ case GAL_SPECLINES_Fe_II_4452: return
GAL_SPECLINES_ANGSTROM_Fe_II_4452;
+ case GAL_SPECLINES_He_I_4471: return GAL_SPECLINES_ANGSTROM_He_I_4471;
+ case GAL_SPECLINES_Fe_II_4489: return
GAL_SPECLINES_ANGSTROM_Fe_II_4489;
+ case GAL_SPECLINES_Fe_II_4491: return
GAL_SPECLINES_ANGSTROM_Fe_II_4491;
+ case GAL_SPECLINES_N_III_4510: return
GAL_SPECLINES_ANGSTROM_N_III_4510;
+ case GAL_SPECLINES_Fe_II_4522: return
GAL_SPECLINES_ANGSTROM_Fe_II_4522;
+ case GAL_SPECLINES_Fe_II_4555: return
GAL_SPECLINES_ANGSTROM_Fe_II_4555;
+ case GAL_SPECLINES_Fe_II_4582: return
GAL_SPECLINES_ANGSTROM_Fe_II_4582;
+ case GAL_SPECLINES_Fe_II_4583: return
GAL_SPECLINES_ANGSTROM_Fe_II_4583;
+ case GAL_SPECLINES_Fe_II_4629: return
GAL_SPECLINES_ANGSTROM_Fe_II_4629;
+ case GAL_SPECLINES_N_III_4634: return
GAL_SPECLINES_ANGSTROM_N_III_4634;
+ case GAL_SPECLINES_N_III_4640: return
GAL_SPECLINES_ANGSTROM_N_III_4640;
+ case GAL_SPECLINES_N_III_4641: return
GAL_SPECLINES_ANGSTROM_N_III_4641;
+ case GAL_SPECLINES_C_III_4647: return
GAL_SPECLINES_ANGSTROM_C_III_4647;
+ case GAL_SPECLINES_C_III_4650: return
GAL_SPECLINES_ANGSTROM_C_III_4650;
+ case GAL_SPECLINES_C_III_5651: return
GAL_SPECLINES_ANGSTROM_C_III_5651;
+ case GAL_SPECLINES_Fe_III_4658: return
GAL_SPECLINES_ANGSTROM_Fe_III_4658;
+ case GAL_SPECLINES_He_II_4685: return
GAL_SPECLINES_ANGSTROM_He_II_4685;
+ case GAL_SPECLINES_Ar_IV_4711: return
GAL_SPECLINES_ANGSTROM_Ar_IV_4711;
+ case GAL_SPECLINES_Ar_IV_4740: return
GAL_SPECLINES_ANGSTROM_Ar_IV_4740;
+ case GAL_SPECLINES_H_beta: return GAL_SPECLINES_ANGSTROM_H_beta;
+ case GAL_SPECLINES_Fe_VII_4893: return
GAL_SPECLINES_ANGSTROM_Fe_VII_4893;
+ case GAL_SPECLINES_Fe_IV_4903: return
GAL_SPECLINES_ANGSTROM_Fe_IV_4903;
+ case GAL_SPECLINES_Fe_II_4923: return
GAL_SPECLINES_ANGSTROM_Fe_II_4923;
+ case GAL_SPECLINES_O_III_4958: return
GAL_SPECLINES_ANGSTROM_O_III_4958;
+ case GAL_SPECLINES_O_III_5006: return
GAL_SPECLINES_ANGSTROM_O_III_5006;
+ case GAL_SPECLINES_Fe_II_5018: return
GAL_SPECLINES_ANGSTROM_Fe_II_5018;
+ case GAL_SPECLINES_Fe_III_5084: return
GAL_SPECLINES_ANGSTROM_Fe_III_5084;
+ case GAL_SPECLINES_Fe_VI_5145: return
GAL_SPECLINES_ANGSTROM_Fe_VI_5145;
+ case GAL_SPECLINES_Fe_VII_5158: return
GAL_SPECLINES_ANGSTROM_Fe_VII_5158;
+ case GAL_SPECLINES_Fe_II_5169: return
GAL_SPECLINES_ANGSTROM_Fe_II_5169;
+ case GAL_SPECLINES_Fe_VI_5176: return
GAL_SPECLINES_ANGSTROM_Fe_VI_5176;
+ case GAL_SPECLINES_Fe_II_5197: return
GAL_SPECLINES_ANGSTROM_Fe_II_5197;
+ case GAL_SPECLINES_N_I_5200: return GAL_SPECLINES_ANGSTROM_N_I_5200;
+ case GAL_SPECLINES_Fe_II_5234: return
GAL_SPECLINES_ANGSTROM_Fe_II_5234;
+ case GAL_SPECLINES_Fe_IV_5236: return
GAL_SPECLINES_ANGSTROM_Fe_IV_5236;
+ case GAL_SPECLINES_Fe_III_5270: return
GAL_SPECLINES_ANGSTROM_Fe_III_5270;
+ case GAL_SPECLINES_Fe_II_5276: return
GAL_SPECLINES_ANGSTROM_Fe_II_5276;
+ case GAL_SPECLINES_Fe_VII_5276: return
GAL_SPECLINES_ANGSTROM_Fe_VII_5276;
+ case GAL_SPECLINES_Fe_XIV: return GAL_SPECLINES_ANGSTROM_Fe_XIV;
+ case GAL_SPECLINES_Ca_V: return GAL_SPECLINES_ANGSTROM_Ca_V;
+ case GAL_SPECLINES_Fe_II_5316_6: return
GAL_SPECLINES_ANGSTROM_Fe_II_5316_6;
+ case GAL_SPECLINES_Fe_II_5316_7: return
GAL_SPECLINES_ANGSTROM_Fe_II_5316_7;
+ case GAL_SPECLINES_Fe_VI_5335: return
GAL_SPECLINES_ANGSTROM_Fe_VI_5335;
+ case GAL_SPECLINES_Fe_VI_5424: return
GAL_SPECLINES_ANGSTROM_Fe_VI_5424;
+ case GAL_SPECLINES_Cl_III_5517: return
GAL_SPECLINES_ANGSTROM_Cl_III_5517;
+ case GAL_SPECLINES_Cl_III_5537: return
GAL_SPECLINES_ANGSTROM_Cl_III_5537;
+ case GAL_SPECLINES_Fe_VI_5637: return
GAL_SPECLINES_ANGSTROM_Fe_VI_5637;
+ case GAL_SPECLINES_Fe_VI_5677: return
GAL_SPECLINES_ANGSTROM_Fe_VI_5677;
+ case GAL_SPECLINES_C_III_5697: return
GAL_SPECLINES_ANGSTROM_C_III_5697;
+ case GAL_SPECLINES_Fe_VII_5720: return
GAL_SPECLINES_ANGSTROM_Fe_VII_5720;
+ case GAL_SPECLINES_N_II_5754: return GAL_SPECLINES_ANGSTROM_N_II_5754;
+ case GAL_SPECLINES_C_IV_5801: return GAL_SPECLINES_ANGSTROM_C_IV_5801;
+ case GAL_SPECLINES_C_IV_5811: return GAL_SPECLINES_ANGSTROM_C_IV_5811;
+ case GAL_SPECLINES_He_I_5875: return GAL_SPECLINES_ANGSTROM_He_I_5875;
+ case GAL_SPECLINES_O_I_6046: return GAL_SPECLINES_ANGSTROM_O_I_6046;
+ case GAL_SPECLINES_Fe_VII_6087: return
GAL_SPECLINES_ANGSTROM_Fe_VII_6087;
+ case GAL_SPECLINES_O_I_6300: return GAL_SPECLINES_ANGSTROM_O_I_6300;
+ case GAL_SPECLINES_S_III_6312: return
GAL_SPECLINES_ANGSTROM_S_III_6312;
+ case GAL_SPECLINES_Si_II_6347: return
GAL_SPECLINES_ANGSTROM_Si_II_6347;
+ case GAL_SPECLINES_O_I_6363: return GAL_SPECLINES_ANGSTROM_O_I_6363;
+ case GAL_SPECLINES_Fe_II_6369: return
GAL_SPECLINES_ANGSTROM_Fe_II_6369;
+ case GAL_SPECLINES_Fe_X: return GAL_SPECLINES_ANGSTROM_Fe_X;
+ case GAL_SPECLINES_Fe_II_6516: return
GAL_SPECLINES_ANGSTROM_Fe_II_6516;
+ case GAL_SPECLINES_N_II_6548: return GAL_SPECLINES_ANGSTROM_N_II_6548;
+ case GAL_SPECLINES_H_alpha: return GAL_SPECLINES_ANGSTROM_H_alpha;
+ case GAL_SPECLINES_N_II_6583: return GAL_SPECLINES_ANGSTROM_N_II_6583;
+ case GAL_SPECLINES_S_II_6716: return GAL_SPECLINES_ANGSTROM_S_II_6716;
+ case GAL_SPECLINES_S_II_6730: return GAL_SPECLINES_ANGSTROM_S_II_6730;
+ case GAL_SPECLINES_O_I_7002: return GAL_SPECLINES_ANGSTROM_O_I_7002;
+ case GAL_SPECLINES_Ar_V: return GAL_SPECLINES_ANGSTROM_Ar_V;
+ case GAL_SPECLINES_He_I_7065: return GAL_SPECLINES_ANGSTROM_He_I_7065;
+ case GAL_SPECLINES_Ar_III_7135: return
GAL_SPECLINES_ANGSTROM_Ar_III_7135;
+ case GAL_SPECLINES_Fe_II_7155: return
GAL_SPECLINES_ANGSTROM_Fe_II_7155;
+ case GAL_SPECLINES_Ar_IV_7170: return
GAL_SPECLINES_ANGSTROM_Ar_IV_7170;
+ case GAL_SPECLINES_Fe_II_7172: return
GAL_SPECLINES_ANGSTROM_Fe_II_7172;
+ case GAL_SPECLINES_C_II_7236: return GAL_SPECLINES_ANGSTROM_C_II_7236;
+ case GAL_SPECLINES_Ar_IV_7237: return
GAL_SPECLINES_ANGSTROM_Ar_IV_7237;
+ case GAL_SPECLINES_O_I_7254: return GAL_SPECLINES_ANGSTROM_O_I_7254;
+ case GAL_SPECLINES_Ar_IV_7262: return
GAL_SPECLINES_ANGSTROM_Ar_IV_7262;
+ case GAL_SPECLINES_He_I_7281: return GAL_SPECLINES_ANGSTROM_He_I_7281;
+ case GAL_SPECLINES_O_II_7319: return GAL_SPECLINES_ANGSTROM_O_II_7319;
+ case GAL_SPECLINES_O_II_7330: return GAL_SPECLINES_ANGSTROM_O_II_7330;
+ case GAL_SPECLINES_Ni_II_7377: return
GAL_SPECLINES_ANGSTROM_Ni_II_7377;
+ case GAL_SPECLINES_Ni_II_7411: return
GAL_SPECLINES_ANGSTROM_Ni_II_7411;
+ case GAL_SPECLINES_Fe_II_7452: return
GAL_SPECLINES_ANGSTROM_Fe_II_7452;
+ case GAL_SPECLINES_N_I_7468: return GAL_SPECLINES_ANGSTROM_N_I_7468;
+ case GAL_SPECLINES_S_XII: return GAL_SPECLINES_ANGSTROM_S_XII;
+ case GAL_SPECLINES_Ar_III_7751: return
GAL_SPECLINES_ANGSTROM_Ar_III_7751;
+ case GAL_SPECLINES_He_I_7816: return GAL_SPECLINES_ANGSTROM_He_I_7816;
+ case GAL_SPECLINES_Ar_I_7868: return GAL_SPECLINES_ANGSTROM_Ar_I_7868;
+ case GAL_SPECLINES_Ni_III: return GAL_SPECLINES_ANGSTROM_Ni_III;
+ case GAL_SPECLINES_Fe_XI_7891: return
GAL_SPECLINES_ANGSTROM_Fe_XI_7891;
+ case GAL_SPECLINES_He_II_8236: return
GAL_SPECLINES_ANGSTROM_He_II_8236;
+ case GAL_SPECLINES_Pa_20: return GAL_SPECLINES_ANGSTROM_Pa_20;
+ case GAL_SPECLINES_Pa_19: return GAL_SPECLINES_ANGSTROM_Pa_19;
+ case GAL_SPECLINES_Pa_18: return GAL_SPECLINES_ANGSTROM_Pa_18;
+ case GAL_SPECLINES_O_I_8446: return GAL_SPECLINES_ANGSTROM_O_I_8446;
+ case GAL_SPECLINES_Pa_17: return GAL_SPECLINES_ANGSTROM_Pa_17;
+ case GAL_SPECLINES_Ca_II_8498: return
GAL_SPECLINES_ANGSTROM_Ca_II_8498;
+ case GAL_SPECLINES_Pa_16: return GAL_SPECLINES_ANGSTROM_Pa_16;
+ case GAL_SPECLINES_Ca_II_8542: return
GAL_SPECLINES_ANGSTROM_Ca_II_8542;
+ case GAL_SPECLINES_Pa_15: return GAL_SPECLINES_ANGSTROM_Pa_15;
+ case GAL_SPECLINES_Cl_II: return GAL_SPECLINES_ANGSTROM_Cl_II;
+ case GAL_SPECLINES_Pa_14: return GAL_SPECLINES_ANGSTROM_Pa_14;
+ case GAL_SPECLINES_Fe_II_8616: return
GAL_SPECLINES_ANGSTROM_Fe_II_8616;
+ case GAL_SPECLINES_Ca_II_8662: return
GAL_SPECLINES_ANGSTROM_Ca_II_8662;
+ case GAL_SPECLINES_Pa_13: return GAL_SPECLINES_ANGSTROM_Pa_13;
+ case GAL_SPECLINES_N_I_8680: return GAL_SPECLINES_ANGSTROM_N_I_8680;
+ case GAL_SPECLINES_N_I_8703: return GAL_SPECLINES_ANGSTROM_N_I_8703;
+ case GAL_SPECLINES_N_I_8711: return GAL_SPECLINES_ANGSTROM_N_I_8711;
+ case GAL_SPECLINES_Pa_12: return GAL_SPECLINES_ANGSTROM_Pa_12;
+ case GAL_SPECLINES_Pa_11: return GAL_SPECLINES_ANGSTROM_Pa_11;
+ case GAL_SPECLINES_Fe_II_8891: return
GAL_SPECLINES_ANGSTROM_Fe_II_8891;
+ case GAL_SPECLINES_Pa_10: return GAL_SPECLINES_ANGSTROM_Pa_10;
+ case GAL_SPECLINES_S_III_9068: return
GAL_SPECLINES_ANGSTROM_S_III_9068;
+ case GAL_SPECLINES_Pa_9: return GAL_SPECLINES_ANGSTROM_Pa_9;
+ case GAL_SPECLINES_S_III_9531: return
GAL_SPECLINES_ANGSTROM_S_III_9531;
+ case GAL_SPECLINES_Pa_epsilon: return
GAL_SPECLINES_ANGSTROM_Pa_epsilon;
+ case GAL_SPECLINES_C_I_9824: return GAL_SPECLINES_ANGSTROM_C_I_9824;
+ case GAL_SPECLINES_C_I_9850: return GAL_SPECLINES_ANGSTROM_C_I_9850;
+ case GAL_SPECLINES_S_VIII: return GAL_SPECLINES_ANGSTROM_S_VIII;
+ case GAL_SPECLINES_He_I_10027: return
GAL_SPECLINES_ANGSTROM_He_I_10027;
+ case GAL_SPECLINES_He_I_10031: return
GAL_SPECLINES_ANGSTROM_He_I_10031;
+ case GAL_SPECLINES_Pa_delta: return GAL_SPECLINES_ANGSTROM_Pa_delta;
+ case GAL_SPECLINES_S_II_10286: return
GAL_SPECLINES_ANGSTROM_S_II_10286;
+ case GAL_SPECLINES_S_II_10320: return
GAL_SPECLINES_ANGSTROM_S_II_10320;
+ case GAL_SPECLINES_S_II_10336: return
GAL_SPECLINES_ANGSTROM_S_II_10336;
+ case GAL_SPECLINES_Fe_XIII: return GAL_SPECLINES_ANGSTROM_Fe_XIII;
+ case GAL_SPECLINES_He_I_10830: return
GAL_SPECLINES_ANGSTROM_He_I_10830;
+ case GAL_SPECLINES_Pa_gamma: return GAL_SPECLINES_ANGSTROM_Pa_gamma;
+
+ /* Limits */
+ case GAL_SPECLINES_LIMIT_LYMAN: return
GAL_SPECLINES_ANGSTROM_LIMIT_LYMAN;
+ case GAL_SPECLINES_LIMIT_BALMER: return
GAL_SPECLINES_ANGSTROM_LIMIT_BALMER;
+ case GAL_SPECLINES_LIMIT_PASCHEN: return
GAL_SPECLINES_ANGSTROM_LIMIT_PASCHEN;
+
default:
error(EXIT_FAILURE, 0, "%s: '%d' not recognized line identifier",
__func__, linecode);
diff --git a/lib/txt.c b/lib/txt.c
index 3cd693c9..314f013f 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -1854,9 +1854,10 @@ txt_write_metadata(FILE *fp, gal_data_t *datall, char
**fmts,
if( (tmp=fmts[ i*FMTS_COLS+1 ]) ) /* If it isn't NULL. */
{
twt=strlen(tmp);
- if(tab0_img1==0 && data->ndim==2) /* +1 for 0 to 10. */
- twt+=(int)(log10(data->dsize[1]))+1+2; /* +2 for the '()'.*/
- tw = twt > tw ? twt : tw;
+ /* A 2D col with second dim of 1 is just a normal 1D col. */
+ if(tab0_img1==0 && data->ndim==2 && data->dsize[1]>1)
+ twt+=(int)(log10(data->dsize[1]))+1+2; /* +1 for 0 to 10. */
+ tw = twt > tw ? twt : tw; /* +2 for the '()'.*/
}
/* Go onto the next data element. */
@@ -1887,8 +1888,9 @@ txt_write_metadata(FILE *fp, gal_data_t *datall, char
**fmts,
for(j=1;j<nlen;++j)
if(!isdigit(nstr[j])) nstr[j] = isdigit(nstr[j-1]) ? ':' : ' ';
- /* For the type, we need to account for vector clumns. */
- if(tab0_img1==0 && data->ndim==2)
+ /* For the type, we need to account for vector clumns. Note that a 2D
+ col with second dim of 1 is just a normal 1D col. */
+ if(tab0_img1==0 && data->ndim==2 && data->dsize[1]>1)
{ if( asprintf(&tstr, "%s(%zu)", fmts[i*FMTS_COLS+1],
data->dsize[1])<0 )
error(EXIT_FAILURE, 0, "%s: asprintf allocation", __func__); }
diff --git a/tests/during-dev.sh b/tests/during-dev.sh
index 7678d7ae..90516c25 100755
--- a/tests/during-dev.sh
+++ b/tests/during-dev.sh
@@ -86,12 +86,15 @@ outdir=
# TEST ASTSCRIPTs: if the problem is in the compiled programs used within
# the script, you have to add a line under the line below
# 'if [ -f "$utility" ]; then rm "$utility"; fi'
-# that will delete that particualr program.
+# that will delete that particular program.
utilname=
arguments=
options=
+
+
+
# RUN THE PROCEDURES
# ==================
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnuastro-commits] master 1817ff60: MakeCatalog: per-slice measurements in vector columns,
Mohammad Akhlaghi <=