gnuastro-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnuastro-commits] master dd024e9: Input info as keywords in output of N


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master dd024e9: Input info as keywords in output of NoiseChisel and Segment
Date: Thu, 9 Aug 2018 18:58:52 -0400 (EDT)

branch: master
commit dd024e91eb9672d2d2fdbf6b7280e084930a09bd
Author: Mohammad Akhlaghi <address@hidden>
Commit: Mohammad Akhlaghi <address@hidden>

    Input info as keywords in output of NoiseChisel and Segment
    
    It can be very helpful to have all the parameters that produced the output
    in the actual output file to allow reproducibility and inspection of
    differences (when playing with parameters) later.
    
    To make this, some minor additions needed to be done in the FITS keyword
    writing functions of the FITS library. The names of the functions that
    write into a `fitsfile' pointer now has a `_in_ptr' suffix to be similar to
    the other functions (for example in writing tables and images). Also, two
    new functions were defined: `gal_fits_key_list_reverse' and
    `gal_fits_key_write_title_in_ptr'.
---
 NEWS                          |  16 ++++
 bin/crop/crop.c               |   4 +-
 bin/crop/onecrop.c            |   2 +-
 bin/noisechisel/noisechisel.c | 142 +++++++++++++++++++++++++++++++++
 bin/segment/main.h            |   2 +-
 bin/segment/segment.c         | 130 ++++++++++++++++++++++++++++++
 bin/segment/ui.c              |   1 +
 doc/gnuastro.texi             | 121 +++++++++++++++++++---------
 lib/fits.c                    | 179 +++++++++++++++++++++++++++++++-----------
 lib/gnuastro/fits.h           |  20 ++++-
 10 files changed, 529 insertions(+), 88 deletions(-)

diff --git a/NEWS b/NEWS
index ed59ad2..970c16a 100644
--- a/NEWS
+++ b/NEWS
@@ -4,10 +4,26 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
 
 ** New features
 
+  NoiseChisel:
+   - Input files and parameters written in first FITS extension.
+
+  Segment:
+   - Input files and parameters written in first FITS extension.
+
+  Library:
+    -- gal_fits_key_list_reverse: Reverse the given list of FITS keywords.
+    -- gal_fits_key_write_title_in_ptr: Write a two-line title in FITS 
keywords.
+    -- gal_fits_key_write_in_ptr: New name of gal_fits_key_write.
+    -- gal_fits_key_write_version_in_ptr: new name of 
gal_fits_key_write_version.
+
 ** Removed features
 
 ** Changed features
 
+  Library:
+    -- gal_fits_key_write: filename and hdu instead of FITS pointer.
+    -- gal_fits_key_write_version: filename and hdu instead of FITS pointer.
+
 ** Bugs fixed
 
 
diff --git a/bin/crop/crop.c b/bin/crop/crop.c
index fe05059..0ce4917 100644
--- a/bin/crop/crop.c
+++ b/bin/crop/crop.c
@@ -231,7 +231,7 @@ crop_mode_img(void *inparam)
           crp->centerfilled=onecrop_center_filled(crp);
 
           /* Add the final headers and close output FITS image: */
-          gal_fits_key_write_version(crp->outfits, NULL, PROGRAM_NAME);
+          gal_fits_key_write_version_in_ptr(NULL, NULL, crp->outfits);
           status=0;
           if( fits_close_file(crp->outfits, &status) )
             gal_fits_io_error(status, "CFITSIO could not close "
@@ -334,7 +334,7 @@ crop_mode_wcs(void *inparam)
           crp->centerfilled=onecrop_center_filled(crp);
 
           /* Write all the dependency versions and close the file. */
-          gal_fits_key_write_version(crp->outfits, NULL, PROGRAM_NAME);
+          gal_fits_key_write_version_in_ptr(NULL, NULL, crp->outfits);
           status=0;
           if( fits_close_file(crp->outfits, &status) )
             gal_fits_io_error(status, "CFITSIO could not close the "
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index a7461f4..87d5099 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -805,7 +805,7 @@ onecrop(struct onecropparams *crp)
       gal_fits_key_list_add_end(&headers, GAL_TYPE_STRING, regionkey,
                                 0, region, 0, "Range of pixels used for "
                                 "this output.", 0, NULL);
-      gal_fits_key_write(ofp, &headers);
+      gal_fits_key_write_in_ptr(&headers, ofp);
 
 
       /* Free the allocated array. */
diff --git a/bin/noisechisel/noisechisel.c b/bin/noisechisel/noisechisel.c
index 060b865..1c5bf08 100644
--- a/bin/noisechisel/noisechisel.c
+++ b/bin/noisechisel/noisechisel.c
@@ -136,6 +136,144 @@ noisechisel_convolve(struct noisechiselparams *p)
 /***********************************************************************/
 /*************                   Output                  ***************/
 /***********************************************************************/
+static void
+noisechisel_params_in_keywords(struct noisechiselparams *p)
+{
+  gal_fits_list_key_t *keys=NULL;
+  struct gal_tile_two_layer_params *tl=&p->cp.tl, *ltl=&p->ltl;
+
+  /* Define the Keywords to write, in the same order as `main.h'. */
+  gal_fits_key_write_filename("input", p->inputname, &keys);
+  gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "hdu", 0, p->cp.hdu,
+                        0, "Extension name or number of input data.", 0,
+                        NULL);
+  if(p->kernelname)
+    {
+      gal_fits_key_write_filename("kernel", p->kernelname, &keys);
+      if(p->khdu)
+        gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "khdu", 0, p->khdu,
+                              0, "HDU/extension of kernel.", 0, NULL);
+    }
+  if(p->convolvedname)
+    {
+      gal_fits_key_write_filename("convolved", p->convolvedname, &keys);
+      if(p->chdu)
+        gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "chdu", 0, p->chdu,
+                              0, "HDU of convolved input.", 0, NULL);
+    }
+  if(p->widekernelname)
+    {
+      gal_fits_key_write_filename("widekernel", p->widekernelname, &keys);
+      if(p->whdu)
+        gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "whdu", 0, p->whdu,
+                              0, "HDU of wide kernel.", 0, NULL);
+    }
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "tilesize_d1", 0,
+                        &tl->tilesize[0], 0,
+                        "Regular tile size on dim.1 (FITS order).", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "tilesize_d2", 0,
+                        &tl->tilesize[1], 0,
+                        "Regular tile size on dim.2 (FITS order).", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "largetilesize_d1", 0,
+                        &ltl->tilesize[0], 0,
+                        "Regular large tile size on dim.1 (FITS order).",
+                        0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "largetilesize_d2", 0,
+                        &ltl->tilesize[1], 0,
+                        "Regular large tile size on dim.2 (FITS order).",
+                        0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "numchannels_d1", 0,
+                        &tl->numchannels[0], 0,
+                        "No. of channels in dim.1 (FITS order).", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "numchannels_d2", 0,
+                        &tl->numchannels[1], 0,
+                        "No. of channels in dim.2 (FITS order).", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "remainderfrac", 0,
+                        &tl->remainderfrac, 0,
+                        "Fraction of remainder to split last tile.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "workoverch", 0,
+                        &tl->workoverch, 0,
+                        "Work (not tile) over channel edges.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "interponlyblank", 0,
+                        &p->cp.interponlyblank, 0,
+                        "Only interpolate over the blank tiles.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "interpnumngb", 0,
+                        &p->cp.interpnumngb, 0,
+                        "No. of neighbors to use for interpolation.",
+                        0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "mirrordist", 0,
+                        &p->mirrordist, 0,
+                        "Max. dist. (error multip.) to find mode.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "modmedqdiff", 0,
+                        &p->modmedqdiff, 0,
+                        "Max. mode and median quant diff. per tile.",
+                        0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "qthresh", 0,
+                        &p->qthresh, 0,
+                        "Quantile threshold on convolved image.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "qthreshtilequant", 0,
+                        &p->qthreshtilequant, 0,
+                        "Remove tiles at higher quantiles.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "smoothwidth", 0,
+                        &p->smoothwidth, 0,
+                        "Flat kernel width to smooth interpolated.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "erode", 0,
+                        &p->erode, 0,
+                        "Number of erosions after thresholding.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "erodengb", 0,
+                        &p->erodengb, 0,
+                        "4 or 8 connectivity in erosion.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "noerodequant", 0,
+                        &p->noerodequant, 0,
+                        "Quantile for no erosion.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "opening", 0,
+                        &p->opening, 0,
+                        "Depth of opening after erosion.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "openingngb", 0,
+                        &p->openingngb, 0,
+                        "4 or 8 connectivity in opening.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT64, "sigmaclipmultip", 0,
+                        &p->sigmaclip[0], 0,
+                        "Multiple of sigma for sigma-clipping.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT64, "sigmaclipend", 0,
+                        &p->sigmaclip[1], 0,
+                        "Termination criteria for sigma-clipping", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "minskyfrac", 0,
+                        &p->minskyfrac, 0,
+                        "Min. fraction of undetected area in tile.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "dthresh", 0,
+                        &p->dthresh, 0,
+                        "Sigma threshold for Pseudo-detections.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "snminarea", 0,
+                        &p->snminarea, 0,
+                        "Min. pseudo-detection area for S/N dist.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "minnumfalse", 0,
+                        &p->minnumfalse, 0,
+                        "Minimum number for S/N estimation.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "snquant", 0,
+                        &p->snquant, 0,
+                        "Quantile in pseudo-det. to define true.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "detgrowquant", 0,
+                        &p->detgrowquant, 0,
+                        "Minimum quant. to expand true detections.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "detgrowmaxholesize", 0,
+                        &p->detgrowmaxholesize, 0,
+                        "Max. area of holes after growth to fill.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "cleangrowndet", 0,
+                        &p->cleangrowndet, 0,
+                        "Remove small S/N grown detections.", 0, NULL);
+
+  /* Reverse the list and write them. */
+  gal_fits_key_list_reverse(&keys);
+  gal_fits_key_write_version(&keys, "NoiseChisel input parameters",
+                             p->cp.output, "0");
+
+}
+
+
+
+
+
 /* Write the output file. */
 static void
 noisechisel_output(struct noisechiselparams *p)
@@ -202,6 +340,10 @@ noisechisel_output(struct noisechiselparams *p)
                              p->cp.output, keys, PROGRAM_NAME);
   p->std->name=NULL;
 
+  /* Write NoiseChisel's parameters as keywords into the first extension of
+     the output. */
+  noisechisel_params_in_keywords(p);
+
   /* Let the user know that the output is written. */
   if(!p->cp.quiet)
     printf("  - Output written to `%s'.\n", p->cp.output);
diff --git a/bin/segment/main.h b/bin/segment/main.h
index 3a72b3b..bb7842e 100644
--- a/bin/segment/main.h
+++ b/bin/segment/main.h
@@ -60,10 +60,10 @@ struct segmentparams
   char               *stdname;  /* File name of Standard deviation image. */
   char                *stdhdu;  /* HDU of Stanard deviation image.        */
   uint8_t            variance;  /* The input STD is actually variance.    */
-  uint8_t              minima;  /* Build clumps from their minima, maxima.*/
   uint8_t           rawoutput;  /* Output only object and clump labels.   */
 
   float            minskyfrac;  /* Undetected area min. frac. in tile.    */
+  uint8_t              minima;  /* Build clumps from their minima, maxima.*/
   size_t            snminarea;  /* Minimum area for segmentation.         */
   uint8_t             checksn;  /* Save the clump S/N values to a file.   */
   size_t          minnumfalse;  /* Min No. of det/seg for true quantile.  */
diff --git a/bin/segment/segment.c b/bin/segment/segment.c
index 189f7d0..b245fc5 100644
--- a/bin/segment/segment.c
+++ b/bin/segment/segment.c
@@ -1048,6 +1048,132 @@ segment_detections(struct segmentparams *p)
 /***********************************************************************/
 /*****************                Output               *****************/
 /***********************************************************************/
+static void
+segment_params_in_keywords(struct segmentparams *p)
+{
+  gal_fits_list_key_t *keys=NULL;
+  struct gal_tile_two_layer_params *tl=&p->cp.tl, *ltl=&p->ltl;
+
+  /* Define the Keywords to write, in the same order as `main.h'. */
+  gal_fits_key_write_filename("input", p->inputname, &keys);
+  gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "hdu", 0, p->cp.hdu,
+                        0, "Extension name or number of input data.", 0,
+                        NULL);
+  if(p->skyname)
+    {
+      gal_fits_key_write_filename("sky", p->skyname, &keys);
+      if(p->skyhdu)
+        gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "skyhdu", 0, p->skyhdu,
+                              0, "HDU containing Sky value to subtract.", 0,
+                              NULL);
+    }
+  if(p->stdname)
+    {
+      gal_fits_key_write_filename("std", p->stdname, &keys);
+      if(p->stdhdu)
+        gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "stdhdu", 0, p->stdhdu,
+                              0, "HDU containing Sky standard deviation.", 0,
+                              NULL);
+    }
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "variance", 0,
+                        &p->variance, 0,
+                        "STD input is actually variance.", 0, NULL);
+  if(p->detectionname)
+    {
+      gal_fits_key_write_filename("detection", p->detectionname, &keys);
+      if(p->khdu)
+        gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "dhdu", 0, p->dhdu,
+                              0, "HDU containing detection image.", 0, NULL);
+    }
+  if(p->kernelname)
+    {
+      gal_fits_key_write_filename("kernel", p->kernelname, &keys);
+      if(p->khdu)
+        gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "khdu", 0, p->khdu,
+                              0, "HDU/extension of kernel.", 0, NULL);
+    }
+  if(p->convolvedname)
+    {
+      gal_fits_key_write_filename("convolved", p->convolvedname, &keys);
+      if(p->chdu)
+        gal_fits_key_list_add(&keys, GAL_TYPE_STRING, "chdu", 0, p->chdu,
+                              0, "HDU of convolved input.", 0, NULL);
+    }
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "onlyclumps", 0,
+                        &p->onlyclumps, 0,
+                        "Finish after finding true clumps.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "grownclumps", 0,
+                        &p->grownclumps, 0,
+                        "Save grown clumps instead of original.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "tilesize_d1", 0,
+                        &tl->tilesize[0], 0,
+                        "Regular tile size on dim.1 (FITS order).", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "tilesize_d2", 0,
+                        &tl->tilesize[1], 0,
+                        "Regular tile size on dim.2 (FITS order).", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "largetilesize_d1", 0,
+                        &ltl->tilesize[0], 0,
+                        "Regular large tile size on dim.1 (FITS order).",
+                        0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "largetilesize_d2", 0,
+                        &ltl->tilesize[1], 0,
+                        "Regular large tile size on dim.2 (FITS order).",
+                        0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "numchannels_d1", 0,
+                        &tl->numchannels[0], 0,
+                        "No. of channels in dim.1 (FITS order).", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "numchannels_d2", 0,
+                        &tl->numchannels[1], 0,
+                        "No. of channels in dim.2 (FITS order).", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "minskyfrac", 0,
+                        &p->minskyfrac, 0,
+                        "Min. fraction of undetected area in tile.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "minima", 0,
+                        &p->minima, 0,
+                        "Built internal clumps from minima.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "snminarea", 0,
+                        &p->snminarea, 0,
+                        "Minimum area of clumps for S/N estimation.",
+                        0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "minnumfalse", 0,
+                        &p->minnumfalse, 0,
+                        "Minimum number for S/N estimation.", 0, NULL);
+  if( !isnan(p->snquant) )
+    gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "snquant", 0,
+                          &p->snquant, 0,
+                          "S/N Quantile of true sky clumps.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "keepmaxnearriver", 0,
+                        &p->keepmaxnearriver, 0,
+                        "Keep clumps with peak touching a river.", 0, NULL);
+  if( isnan(p->snquant) )
+    gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "clumpsnthresh", 0,
+                          &p->clumpsnthresh, 0,
+                          "S/N threshold of true clumps.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "gthresh", 0,
+                        &p->gthresh, 0,
+                        "Multiple of STD to stop growing clumps.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_SIZE_T, "minriverlength", 0,
+                        &p->minriverlength, 0,
+                        "Minimum len of useful grown clump rivers.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_FLOAT32, "objbordersn", 0,
+                        &p->objbordersn, 0,
+                        "Min. S/N for grown clumps as one object.", 0, NULL);
+  gal_fits_key_list_add(&keys, GAL_TYPE_UINT8, "checksegmentation", 0,
+                        &p->checksegmentation, 0,
+                        "Store segmentation steps in a file.", 0, NULL);
+
+
+  /* Reverse the list and write them. */
+  gal_fits_key_list_reverse(&keys);
+  gal_fits_key_write_version(&keys, "NoiseChisel input parameters",
+                             p->cp.output, "0");
+
+}
+
+
+
+
+
 void
 segment_output(struct segmentparams *p)
 {
@@ -1121,6 +1247,10 @@ segment_output(struct segmentparams *p)
       p->std->name=NULL;
     }
 
+  /* Write the input parameters as FITS keyword in the first extension of
+     the output file. */
+  segment_params_in_keywords(p);
+
   /* Let the user know that the output is written. */
   if(!p->cp.quiet)
     printf("  - Output written to `%s'.\n", p->cp.output);
diff --git a/bin/segment/ui.c b/bin/segment/ui.c
index 00b33a3..168f8e7 100644
--- a/bin/segment/ui.c
+++ b/bin/segment/ui.c
@@ -118,6 +118,7 @@ ui_initialize_options(struct segmentparams *p,
   p->medstd              = NAN;
   p->minstd              = NAN;
   p->maxstd              = NAN;
+  p->snquant             = NAN;
   p->clumpsnthresh       = NAN;
 
   /* Modify common options. */
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 2d64c81..d8a8d60 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -16080,6 +16080,19 @@ the different check images, see the description for 
the @option{--check*}
 options in @ref{Detection options} (this can be disabled with
 @option{--continueaftercheck}).
 
+Similar to all Gnuastro's FITS outputs, the zero-th extension/HDU of the
+main output file only contains header keywords and image or table. It
+contains the NoiseChisel input files and parameters (option names and
+values) as FITS keywords. Note that if an option name is longer than 8
+characters, the keyword name is the second word. The first word is
address@hidden Also note that according to the FITS standard, the keyword
+names must be in capital letters, therefore, if you want to use Grep to
+inspect these keywords, use the @option{-i} option, like the example below.
+
address@hidden
+$ astfits image_detected.fits -h0 | grep -i snquant
address@hidden example
+
 The last two extensions of the output are the Sky and its Standard
 deviation, see @ref{Sky value} for a complete explanation. They are
 calculated on the tile grid that you defined for NoiseChisel. By default
@@ -16856,37 +16869,21 @@ created. This behavior can be disabled with 
@option{--continueaftercheck}.
 @subsubsection Segment output
 
 The main output of Segment are two label datasets (with integer types,
-separating the dataset's elements into different classes) with
-HDU/extension names of @code{CLUMPS} and @code{OBJECTS}. For a complete
-definition of clumps and objects, please see Section 3.2 of
address@hidden://arxiv.org/abs/1505.01664, Akhlaghi and Ichikawa [2015]} and
address@hidden options}.
-
-The clumps are ``true'' local maxima (minima if @option{--minima} is
-called) and their surrounding pixels until a local minimum/maximum (caused
-by noise fluctuations, or another ``true'' clump). Therefore it may happen
-that some of the input detections aren't covered by clumps at all (very
-diffuse objects without any strong peak), while some objects may contain
-many clumps. Even in those that have clumps, there will be regions that are
-too diffuse. The diffuse regions (within the input detected regions) are
-given a negative label (-1) to help you separate them from the undetected
-regions (with a value of zero).
+separating the dataset's elements into different classes). They have
+HDU/extension names of @code{CLUMPS} and @code{OBJECTS}.
 
-Each clump is labeled with respect to its host object. Therefore, if an
-object has three clumps for example, the clumps within it have labels 1, 2
-and 3. As a result, if an initial detected region has multiple objects,
-each with a single clump, all the clumps will have a label of 1. The total
-number of clumps in the dataset is stored in the @code{NCLUMPS} keyword of
-the @code{CLUMPS} extension and printed in the verbose output of Segment
-(when @option{--quiet} is not called).
+Similar to all Gnuastro's FITS outputs, the zero-th extension/HDU of the
+main output file only contains header keywords and image or table. It
+contains the Segment input files and parameters (option names and values)
+as FITS keywords. Note that if an option name is longer than 8 characters,
+the keyword name is the second word. The first word is
address@hidden Also note that according to the FITS standard, the keyword
+names must be in capital letters, therefore, if you want to use Grep to
+inspect these keywords, use the @option{-i} option, like the example below.
 
-The @code{OBJECTS} extension of the output will give a positive
-counter/label to every detected pixel in the input. As described in
-Akhlaghi and Ichikawa [2015], the true clumps are grown until a certain
-threshold. If the grown clumps touch other clumps and the connection is
-strong enough, they are considered part of the same @emph{object}. Once
-objects (grown clumps) are identified, they are grown to cover the whole
-detected area.
address@hidden
+$ astfits image_segmented.fits -h0 | grep -i snquant
address@hidden example
 
 @cindex DS9
 @cindex SAO DS9
@@ -16908,8 +16905,37 @@ The @code{OBJECTS} and @code{CLUMPS} extensions can be 
used as input into
 want to treat each clump separately, you can give a very large value (or
 even a NaN, which will always fail) to the @option{--gthresh} option (for
 example @code{--gthresh=1e10} or @code{--gthresh=nan}), see
address@hidden options}. The options to configure the output of Segment
-are listed below:
address@hidden options}.
+
+For a complete definition of clumps and objects, please see Section 3.2 of
address@hidden://arxiv.org/abs/1505.01664, Akhlaghi and Ichikawa [2015]} and
address@hidden options}. The clumps are ``true'' local maxima (minima if
address@hidden is called) and their surrounding pixels until a local
+minimum/maximum (caused by noise fluctuations, or another ``true''
+clump). Therefore it may happen that some of the input detections aren't
+covered by clumps at all (very diffuse objects without any strong peak),
+while some objects may contain many clumps. Even in those that have clumps,
+there will be regions that are too diffuse. The diffuse regions (within the
+input detected regions) are given a negative label (-1) to help you
+separate them from the undetected regions (with a value of zero).
+
+Each clump is labeled with respect to its host object. Therefore, if an
+object has three clumps for example, the clumps within it have labels 1, 2
+and 3. As a result, if an initial detected region has multiple objects,
+each with a single clump, all the clumps will have a label of 1. The total
+number of clumps in the dataset is stored in the @code{NCLUMPS} keyword of
+the @code{CLUMPS} extension and printed in the verbose output of Segment
+(when @option{--quiet} is not called).
+
+The @code{OBJECTS} extension of the output will give a positive
+counter/label to every detected pixel in the input. As described in
+Akhlaghi and Ichikawa [2015], the true clumps are grown until a certain
+threshold. If the grown clumps touch other clumps and the connection is
+strong enough, they are considered part of the same @emph{object}. Once
+objects (grown clumps) are identified, they are grown to cover the whole
+detected area.
+
+The options to configure the output of Segment are listed below:
 
 @table @option
 @item --continueaftercheck
@@ -24722,6 +24748,19 @@ the end of the list. Use this function if you want the 
keywords to be
 written in the same order that you add nodes to the list of keywords.
 @end deftypefun
 
address@hidden void gal_fits_key_list_reverse (gal_fits_list_key_t 
@code{**list})
+Reverse the input list of keywords.
address@hidden deftypefun
+
address@hidden void gal_fits_key_write_title_in_ptr (char @code{*title}, 
fitsfile @code{*fptr})
+Add two lines of ``title'' keywords to the given CFITSIO @code{fptr}
+pointer. The first line will be blank and the second will have the string
+in @code{title} roughly in the middle of the line (a fixed distance from
+the start of the keyword line). A title in the list of keywords helps in
+classifying the keywords into groups and inspecting them by eye. If
address@hidden, this function won't do anything.
address@hidden deftypefun
+
 @deftypefun void gal_fits_key_write_filename (char @code{*keynamebase}, char 
@code{*filename}, gal_fits_list_key_t @code{**list})
 Put @file{filename} into the @code{gal_fits_list_key_t} list (possibly
 broken up into multiple keywords) to later write into a HDU header. The
@@ -24744,12 +24783,24 @@ keyword lines along with a comment @code{WCS 
information} before writing
 each keyword record.
 @end deftypefun
 
address@hidden void gal_fits_key_write (fitsfile @code{*fptr}, 
gal_fits_list_key_t @code{**keylist})
-Write the list of keywords in @code{keylist} into the CFITSIO
address@hidden
address@hidden void gal_fits_key_write (gal_fits_list_key_t @code{**keylist}, 
char @code{*title}, char @code{*filename}, char @code{*hdu})
+Write the list of keywords in @code{keylist} into the @code{hdu} extension
+of the file called @code{filename} (it must already exist).
address@hidden deftypefun
+
address@hidden void gal_fits_key_write_in_ptr (gal_fits_list_key_t 
@code{**keylist}, fitsfile @code{*fptr})
+Write the list of keywords in @code{keylist} into the given CFITSIO
address@hidden pointer.
address@hidden deftypefun
+
address@hidden void gal_fits_key_write_version (gal_fits_list_key_t 
@code{**keylist}, char @code{*title}, char @code{*filename}, char @code{*hdu})
+Write the (optional, when @code{keylist!=NULL}) given list of keywords
+under the optional FITS keyword @code{title}, then print all the important
+version and date information. This is basically, just a wrapper over
address@hidden
 @end deftypefun
 
address@hidden void gal_fits_key_write_version (fitsfile @code{*fptr}, 
gal_fits_list_key_t @code{*headers}, char @code{*program_name})
address@hidden void gal_fits_key_write_version_in_ptr (gal_fits_list_key_t 
@code{**keylist}, char @code{*title}, fitsfile @code{*fptr})
 Write or update (all the) keyword(s) in @code{headers} into the FITS
 pointer, but also the date, name of your program (@code{program_name}),
 along with the versions of CFITSIO, WCSLIB (when available), GSL, Gnuastro,
diff --git a/lib/fits.c b/lib/fits.c
index 772c621..4a6ffc2 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -1152,6 +1152,75 @@ gal_fits_key_list_add_end(gal_fits_list_key_t **list, 
uint8_t type,
 
 
 void
+gal_fits_key_list_reverse(gal_fits_list_key_t **list)
+{
+  gal_fits_list_key_t *in=*list, *tmp=in, *reversed=NULL;
+
+  /* Only do the reversal if there is more than one element. */
+  if(in && in->next)
+    {
+      /* Fill the `reversed' list. */
+      while(in!=NULL)
+        {
+          tmp=in->next;
+          in->next=reversed;
+          reversed=in;
+          in=tmp;
+        }
+
+      /* Write the reversed list into the input pointer. */
+      *list=reversed;
+    }
+}
+
+
+
+
+
+/* Write a blank keyword field and a title under it in the specified FITS
+   file pointer. */
+void
+gal_fits_key_write_title_in_ptr(char *title, fitsfile *fptr)
+{
+  size_t i;
+  int status=0;
+  char *cp, *cpf, blankrec[80], titlerec[80];
+
+  /* Just in case title is `NULL'. */
+  if(title)
+    {
+      /* A small sanity check. */
+      if( strlen(title) + strlen(GAL_FITS_KEY_TITLE_START) > 78 )
+        fprintf(stderr, "%s: FITS keyword title `%s' is too long to be fully "
+                "included in the keyword record (80 characters, where the "
+                "title is prefixed with %zu space characters)",
+                __func__, title, strlen(GAL_FITS_KEY_TITLE_START));
+
+      /* Set the last element of the blank array. */
+      cpf=blankrec+79;
+      *cpf='\0';
+      titlerec[79]='\0';
+      cp=blankrec; do *cp=' '; while(++cp<cpf);
+
+      /* Print the blank lines before the title */
+      if(fits_write_record(fptr, blankrec, &status))
+        gal_fits_io_error(status, NULL);
+
+      /* Print the title */
+      sprintf(titlerec, "%s%s", GAL_FITS_KEY_TITLE_START, title);
+      for(i=strlen(titlerec);i<79;++i)
+        titlerec[i]=' ';
+      if(fits_write_record(fptr, titlerec, &status))
+        gal_fits_io_error(status, NULL);
+    }
+}
+
+
+
+
+
+/* Write a filename into keyword values. */
+void
 gal_fits_key_write_filename(char *keynamebase, char *filename,
                             gal_fits_list_key_t **list)
 {
@@ -1165,6 +1234,7 @@ gal_fits_key_write_filename(char *keynamebase, char 
*filename,
      to take three from it.*/
   maxlength=FLEN_VALUE-3;
 
+  /* Parse the filename and see when it is necessary to break it. */
   i=0;
   while(i<len)
     {
@@ -1174,7 +1244,10 @@ gal_fits_key_write_filename(char *keynamebase, char 
*filename,
       if(keyname==NULL)
         error(EXIT_FAILURE, errno, "%s: %d bytes for `keyname'", __func__,
               FLEN_KEYWORD);
-      sprintf(keyname, "%s_%zu", keynamebase, numkey++);
+      if(len<maxlength)
+        gal_checkset_allocate_copy(keynamebase, &keyname);
+      else
+        sprintf(keyname, "%s_%zu", keynamebase, numkey++);
 
       /* Set the keyword value: */
       errno=0;
@@ -1228,24 +1301,10 @@ gal_fits_key_write_filename(char *keynamebase, char 
*filename,
 void
 gal_fits_key_write_wcsstr(fitsfile *fptr, char *wcsstr, int nkeyrec)
 {
-  size_t i;
   int h, status=0;
-  char *cp, *cpf, blankrec[80], titlerec[80];
 
-  /* Set the last element of the blank array. */
-  cpf=blankrec+79;
-  *cpf='\0';
-  titlerec[79]='\0';
-  cp=blankrec; do *cp=' '; while(++cp<cpf);
-
-  /* Print the first two lines before the WCS header information. */
-  if(fits_write_record(fptr, blankrec, &status))
-    gal_fits_io_error(status, NULL);
-  sprintf(titlerec, "%sWCS information", GAL_FITS_KEY_TITLE_START);
-  for(i=strlen(titlerec);i<79;++i)
-    titlerec[i]=' ';
-  if(fits_write_record(fptr, titlerec, &status))
-    gal_fits_io_error(status, NULL);
+  /* Write the title. */
+  gal_fits_key_write_title_in_ptr("World Coordinate System (WCS)", fptr);
 
   /* Write the keywords one by one: */
   for(h=0;h<nkeyrec-1;++h)
@@ -1257,11 +1316,35 @@ gal_fits_key_write_wcsstr(fitsfile *fptr, char *wcsstr, 
int nkeyrec)
 
 
 
+/* Write the given list of header keywords into the specified HDU of the
+   specified FITS file. */
+void
+gal_fits_key_write(gal_fits_list_key_t **keylist, char *title,
+                   char *filename, char *hdu)
+{
+  int status=0;
+  fitsfile *fptr=gal_fits_hdu_open(filename, hdu, READWRITE);
+
+  /* Write the title */
+  gal_fits_key_write_title_in_ptr(title, fptr);
+
+  /* Write the keywords into the  */
+  gal_fits_key_write_in_ptr(keylist, fptr);
+
+  /* Close the input FITS file. */
+  fits_close_file(fptr, &status);
+  gal_fits_io_error(status, NULL);
+}
+
+
+
+
+
 /* Write the keywords in the gal_fits_list_key_t linked list to the FITS
    file. Every keyword that is written is freed, that is why we need the
    pointer to the linked list (to correct it after we finish). */
 void
-gal_fits_key_write(fitsfile *fptr, gal_fits_list_key_t **keylist)
+gal_fits_key_write_in_ptr(gal_fits_list_key_t **keylist, fitsfile *fptr)
 {
   int status=0;
   gal_fits_list_key_t *tmp, *ttmp;
@@ -1308,15 +1391,34 @@ gal_fits_key_write(fitsfile *fptr, gal_fits_list_key_t 
**keylist)
 
 
 
+/* Write the given list of header keywords and version info into the give
+   file. */
 void
-gal_fits_key_write_version(fitsfile *fptr, gal_fits_list_key_t *headers,
-                           char *program_name)
+gal_fits_key_write_version(gal_fits_list_key_t **keylist, char *title,
+                           char *filename, char *hdu)
+{
+  int status=0;
+  fitsfile *fptr=gal_fits_hdu_open(filename, hdu, READWRITE);
+
+  /* Write the given keys followed by the versions. */
+  gal_fits_key_write_version_in_ptr(keylist, title, fptr);
+
+  /* Close the input FITS file. */
+  fits_close_file(fptr, &status);
+  gal_fits_io_error(status, NULL);
+}
+
+
+
+
+
+void
+gal_fits_key_write_version_in_ptr(gal_fits_list_key_t **keylist, char *title,
+                                  fitsfile *fptr)
 {
-  size_t i;
   int status=0;
   char *gitdescribe;
   char cfitsioversion[20];
-  char *cp, *cpf, blankrec[80], titlerec[80];
 
   /* Before WCSLIB 5.0, the wcslib_version function was not
      defined. Sometime in the future were everyone has moved to more
@@ -1328,30 +1430,15 @@ gal_fits_key_write_version(fitsfile *fptr, 
gal_fits_list_key_t *headers,
   const char *wcslibversion_const;
 #endif
 
-  /* Set the last element of the blank array. */
-  cpf=blankrec+79;
-  *cpf='\0';
-  titlerec[79]='\0';
-  cp=blankrec; do *cp=' '; while(++cp<cpf);
-
-  /* If any header keywords are specified add them: */
-  if(headers)
+  /* If any header keywords are specified, add them: */
+  if(keylist && *keylist)
     {
-      fits_write_record(fptr, blankrec, &status);
-      sprintf(titlerec, "%s%s", GAL_FITS_KEY_TITLE_START,
-              program_name ? program_name : PACKAGE_NAME);
-      for(i=strlen(titlerec);i<79;++i) titlerec[i]=' ';
-      fits_write_record(fptr, titlerec, &status);
-      gal_fits_key_write(fptr, &headers);
+      gal_fits_key_write_title_in_ptr(title?title:"Specific keys", fptr);
+      gal_fits_key_write_in_ptr(keylist, fptr);
     }
 
-
-  /* Start printing the version information */
-  fits_write_record(fptr, blankrec, &status);
-  sprintf(titlerec, "%sVersions and date", GAL_FITS_KEY_TITLE_START);
-  for(i=strlen(titlerec);i<79;++i) titlerec[i]=' ';
-  fits_write_record(fptr, titlerec, &status);
-  gal_fits_io_error(status, NULL);
+  /* Print `Versions and date' title. */
+  gal_fits_key_write_title_in_ptr("Versions and date", fptr);
 
   /* Set the version of CFITSIO as a string. */
   sprintf(cfitsioversion, "%-.2f", CFITSIO_VERSION);
@@ -1838,7 +1925,7 @@ gal_fits_img_write(gal_data_t *data, char *filename,
   fptr=gal_fits_img_write_to_ptr(data, filename);
 
   /* Write all the headers and the version information. */
-  gal_fits_key_write_version(fptr, headers, program_string);
+  gal_fits_key_write_version_in_ptr(&headers, program_string, fptr);
 
   /* Close the FITS file. */
   fits_close_file(fptr, &status);
@@ -1917,7 +2004,7 @@ gal_fits_img_write_corr_wcs_str(gal_data_t *input, char 
*filename,
     }
 
   /* Write all the headers and the version information. */
-  gal_fits_key_write_version(fptr, headers, program_string);
+  gal_fits_key_write_version_in_ptr(&headers, program_string, fptr);
 
   /* Close the file and return. */
   fits_close_file(fptr, &status);
@@ -2874,7 +2961,7 @@ gal_fits_tab_write(gal_data_t *cols, gal_list_str_t 
*comments,
 
 
   /* Write all the headers and the version information. */
-  gal_fits_key_write_version(fptr, NULL, NULL);
+  gal_fits_key_write_version_in_ptr(NULL, NULL, fptr);
 
 
   /* Clean up and close the FITS file. Note that each element in the
diff --git a/lib/gnuastro/fits.h b/lib/gnuastro/fits.h
index 2960378..c922c07 100644
--- a/lib/gnuastro/fits.h
+++ b/lib/gnuastro/fits.h
@@ -185,6 +185,12 @@ gal_fits_key_list_add_end(gal_fits_list_key_t **list, 
uint8_t type,
                           char *comment, int cfree, char *unit);
 
 void
+gal_fits_key_list_reverse(gal_fits_list_key_t **list);
+
+void
+gal_fits_key_write_title_in_ptr(char *title, fitsfile *fptr);
+
+void
 gal_fits_key_write_filename(char *keynamebase, char *filename,
                             gal_fits_list_key_t **list);
 
@@ -192,11 +198,19 @@ void
 gal_fits_key_write_wcsstr(fitsfile *fptr, char *wcsstr, int nkeyrec);
 
 void
-gal_fits_key_write(fitsfile *fptr, gal_fits_list_key_t **keylist);
+gal_fits_key_write(gal_fits_list_key_t **keylist, char *title,
+                   char *filename, char *hdu);
+
+void
+gal_fits_key_write_in_ptr(gal_fits_list_key_t **keylist, fitsfile *fptr);
+
+void
+gal_fits_key_write_version(gal_fits_list_key_t **keylist, char *title,
+                           char *filename, char *hdu);
 
 void
-gal_fits_key_write_version(fitsfile *fptr, gal_fits_list_key_t *headers,
-                           char *program_string);
+gal_fits_key_write_version_in_ptr(gal_fits_list_key_t **keylist, char *title,
+                                  fitsfile *fptr);
 
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]