gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master e990860 029/113: Merged recent updates in mast


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master e990860 029/113: Merged recent updates in master
Date: Fri, 16 Apr 2021 10:33:37 -0400 (EDT)

branch: master
commit e990860cd6439c2fc8651e8640b580bb3073c3c4
Merge: 4d2508f a05dafe
Author: Mohammad Akhlaghi <akhlaghi@gnu.org>
Commit: Mohammad Akhlaghi <akhlaghi@gnu.org>

    Merged recent updates in master
    
    Recent changes in master are now merged into this branch.
---
 NEWS                             |   2 +
 THANKS                           |   2 +
 bin/arithmetic/ui.c              |   4 +-
 bin/convertt/eps.c               |   4 +-
 bin/convertt/ui.c                |   2 +-
 bin/convolve/ui.c                |   8 +-
 bin/crop/onecrop.c               |   4 +-
 bin/fits/fits.c                  |   2 +-
 bin/fits/ui.c                    |   2 +-
 bin/mknoise/ui.c                 |   2 +-
 bin/mkprof/mkprof.c              |   2 +-
 bin/mkprof/ui.c                  |   4 +-
 bin/noisechisel/clumps.c         | 106 +++++++++++++------------
 bin/noisechisel/ui.c             |   2 +-
 bin/warp/ui.c                    |   2 +-
 doc/announce-acknowledge.txt     |   2 +
 doc/gnuastro.texi                |  16 ++--
 lib/checkset.c                   | 164 +++++++++++++++++++--------------------
 lib/fits.c                       |  50 +++++++++++-
 lib/gnuastro-internal/checkset.h |  14 ++--
 lib/options.c                    |   2 +-
 lib/txt.c                        |   2 +-
 22 files changed, 230 insertions(+), 168 deletions(-)

diff --git a/NEWS b/NEWS
index ec9901a..c3380cb 100644
--- a/NEWS
+++ b/NEWS
@@ -148,6 +148,8 @@ GNU Astronomy Utilities NEWS                          -*- 
outline -*-
 
   Arithmetic with one file and no operators (bug #51559).
 
+  NoiseChisel segfault when detection contains no clumps (bug #51906).
+
 
 
 
diff --git a/THANKS b/THANKS
index a672f3d..0b5e215 100644
--- a/THANKS
+++ b/THANKS
@@ -19,9 +19,11 @@ support in Gnuastro. The list is ordered alphabetically (by 
family name).
     Karl Berry                           karl@gnu.org
     Roland Bacon                         roland.bacon@univ-lyon1.fr
     Nicolas Bouché                       nicolas.bouche@irap.omp.eu
+    Fernando Buitrago                    fbuitrago@oal.ul.pt
     Adrian Bunk                          bunk@debian.org
     Rosa Calvi                           rcalvi@iac.es
     Antonio Diaz Diaz                    antonio@gnu.org
+    Stephen Hamer                        stephen.hamer@univ-lyon1.fr
     Takashi Ichikawa                     ichikawa@astr.tohoku.ac.jp
     Raúl Infante Sainz                   infantesainz@gmail.com
     Brandon Invergo                      brandon@gnu.org
diff --git a/bin/arithmetic/ui.c b/bin/arithmetic/ui.c
index e3cbac3..8e591df 100644
--- a/bin/arithmetic/ui.c
+++ b/bin/arithmetic/ui.c
@@ -256,8 +256,8 @@ ui_check_options_and_arguments(struct arithmeticparams *p)
           if(output_checked==0)
             {
               if(p->cp.output)
-                gal_checkset_check_remove_file(p->cp.output, 0,
-                                               p->cp.dontdelete);
+                gal_checkset_writable_remove(p->cp.output, 0,
+                                             p->cp.dontdelete);
               else
                 p->cp.output=gal_checkset_automatic_output(&p->cp, token->v,
                                                            "_arith.fits");
diff --git a/bin/convertt/eps.c b/bin/convertt/eps.c
index 3b3d06f..efa3e33 100644
--- a/bin/convertt/eps.c
+++ b/bin/convertt/eps.c
@@ -390,11 +390,11 @@ eps_write_eps_or_pdf(struct converttparams *p)
   if(p->outformat==OUT_FORMAT_EPS)
     {
       epsfilename=p->cp.output;
-      gal_checkset_check_remove_file(epsfilename, 0, p->cp.dontdelete);
+      gal_checkset_writable_remove(epsfilename, 0, p->cp.dontdelete);
     }
   else if (p->outformat==OUT_FORMAT_PDF)
     {
-      gal_checkset_check_remove_file(p->cp.output, 0, p->cp.dontdelete);
+      gal_checkset_writable_remove(p->cp.output, 0, p->cp.dontdelete);
       epsfilename=gal_checkset_automatic_output(&p->cp, p->cp.output, ".ps");
     }
   else
diff --git a/bin/convertt/ui.c b/bin/convertt/ui.c
index 5979925..2f9f4d2 100644
--- a/bin/convertt/ui.c
+++ b/bin/convertt/ui.c
@@ -726,7 +726,7 @@ ui_set_output(struct converttparams *p)
     }
 
   /* Check if the output already exists. */
-  gal_checkset_check_remove_file(cp->output, 0, cp->dontdelete);
+  gal_checkset_writable_remove(cp->output, 0, cp->dontdelete);
 }
 
 
diff --git a/bin/convolve/ui.c b/bin/convolve/ui.c
index 342a045..34c6c89 100644
--- a/bin/convolve/ui.c
+++ b/bin/convolve/ui.c
@@ -334,19 +334,19 @@ ui_preparations(struct convolveparams *p)
   /* Set the output name if the user hasn't set it. */
   if(cp->output==NULL)
     cp->output=gal_checkset_automatic_output(cp, p->filename, outsuffix);
-  gal_checkset_check_remove_file(cp->output, 0, cp->dontdelete);
+  gal_checkset_writable_remove(cp->output, 0, cp->dontdelete);
   if(p->checkfreqsteps)
     {
       p->freqstepsname=gal_checkset_automatic_output(cp, p->filename,
                                                      "_freqsteps.fits");
-      gal_checkset_check_remove_file(p->freqstepsname, 0, cp->dontdelete);
+      gal_checkset_writable_remove(p->freqstepsname, 0, cp->dontdelete);
     }
   if(cp->tl.checktiles)
     {
       cp->tl.tilecheckname=gal_checkset_automatic_output(cp, p->filename,
                                                          "_tiled.fits");
-      gal_checkset_check_remove_file(cp->tl.tilecheckname, 0,
-                                     cp->dontdelete);
+      gal_checkset_writable_remove(cp->tl.tilecheckname, 0,
+                                   cp->dontdelete);
     }
 
 
diff --git a/bin/crop/onecrop.c b/bin/crop/onecrop.c
index 80a2257..5afff2c 100644
--- a/bin/crop/onecrop.c
+++ b/bin/crop/onecrop.c
@@ -460,7 +460,7 @@ onecrop_name(struct onecropparams *crp)
                  p->suffix);
 
       /* Make sure the file doesn't exist. */
-      gal_checkset_check_remove_file(crp->name, 0, cp->dontdelete);
+      gal_checkset_writable_remove(crp->name, 0, cp->dontdelete);
     }
   else
     {
@@ -468,7 +468,7 @@ onecrop_name(struct onecropparams *crp)
       if(p->outnameisfile)            /* An output file was specified. */
         {
           crp->name=cp->output;
-          gal_checkset_check_remove_file(crp->name, 0, cp->dontdelete);
+          gal_checkset_writable_remove(crp->name, 0, cp->dontdelete);
         }
       else          /* The output was a directory, use automatic output. */
         crp->name=gal_checkset_automatic_output(cp,
diff --git a/bin/fits/fits.c b/bin/fits/fits.c
index 60db9f6..e96e45d 100644
--- a/bin/fits/fits.c
+++ b/bin/fits/fits.c
@@ -313,7 +313,7 @@ fits_hdu_copy(struct fitsparams *p, int cut1_copy0, int *r)
 int
 fits(struct fitsparams *p)
 {
-  int r=EXIT_SUCCESS, printhduinfo=1;;
+  int r=EXIT_SUCCESS, printhduinfo=1;
 
   switch(p->mode)
     {
diff --git a/bin/fits/ui.c b/bin/fits/ui.c
index a359994..6f1388e 100644
--- a/bin/fits/ui.c
+++ b/bin/fits/ui.c
@@ -257,7 +257,7 @@ ui_read_check_only_options(struct fitsparams *p)
 
       /* Make sure the output name is set. */
       if(p->cp.output)
-        gal_checkset_check_remove_file(p->filename, 1, p->cp.dontdelete);
+        gal_checkset_writable_remove(p->cp.output, 1, p->cp.dontdelete);
       else
         p->cp.output=gal_checkset_automatic_output(&p->cp, p->filename,
                                                    "_ext.fits");
diff --git a/bin/mknoise/ui.c b/bin/mknoise/ui.c
index 79ab5a0..7388979 100644
--- a/bin/mknoise/ui.c
+++ b/bin/mknoise/ui.c
@@ -297,7 +297,7 @@ ui_preparations(struct mknoiseparams *p)
 
   /* Set the output name: */
   if(p->cp.output)
-    gal_checkset_check_remove_file(p->cp.output, 0, p->cp.dontdelete);
+    gal_checkset_writable_remove(p->cp.output, 0, p->cp.dontdelete);
   else
     p->cp.output=gal_checkset_automatic_output(&p->cp, p->inputname,
                                                "_noised.fits");
diff --git a/bin/mkprof/mkprof.c b/bin/mkprof/mkprof.c
index 3bc4e5e..bbe6768 100644
--- a/bin/mkprof/mkprof.c
+++ b/bin/mkprof/mkprof.c
@@ -139,7 +139,7 @@ saveindividual(struct mkonthread *mkp)
   else
     {
       asprintf(&filename, "%s%zu_%s", outdir, ibq->id, p->basename);
-      gal_checkset_check_remove_file(filename, 0, p->cp.dontdelete);
+      gal_checkset_writable_remove(filename, 0, p->cp.dontdelete);
     }
 
 
diff --git a/bin/mkprof/ui.c b/bin/mkprof/ui.c
index a1e999d..9f9df1f 100644
--- a/bin/mkprof/ui.c
+++ b/bin/mkprof/ui.c
@@ -678,8 +678,8 @@ ui_check_options_and_arguments(struct mkprofparams *p)
   /* If a merged image is requested (or `--kernel' the option is called),
      then delete the final filename if it exists. */
   if(p->nomerged==0 && p->kernel)
-    gal_checkset_check_remove_file(p->mergedimgname, p->cp.keep,
-                                   p->cp.dontdelete);
+    gal_checkset_writable_remove(p->mergedimgname, p->cp.keep,
+                                 p->cp.dontdelete);
 }
 
 
diff --git a/bin/noisechisel/clumps.c b/bin/noisechisel/clumps.c
index 4c891fb..5f5fdb9 100644
--- a/bin/noisechisel/clumps.c
+++ b/bin/noisechisel/clumps.c
@@ -91,7 +91,7 @@ clumps_oversegment(struct clumps_thread_params *cltprm)
                                   GAL_TYPE_INVALID, 2, checkdsize,
                                   NULL, 0, 0, NULL, NULL, NULL);
   tile->block=p->conv;
-  gal_checkset_check_remove_file(filename, 0, 0);
+  gal_checkset_writable_remove(filename, 0, 0);
   if(p->cp.numthreads!=1)
     error(EXIT_FAILURE, 0, "in the debugging mode of `clumps_oversegment' "
           "only one thread must be used");
@@ -1457,57 +1457,67 @@ clumps_det_keep_true_relabel(struct 
clumps_thread_params *cltprm)
   size_t ndim=p->input->ndim, *dsize=p->input->dsize;
 
   int istouching;
-  size_t *s, *sf;
-  float *sn=cltprm->sn->array;
-  int32_t *l, *lf, curlab=1, *clabel=p->clabel->array;
-  size_t i, *dinc=gal_dimension_increment(ndim, dsize);
-  int32_t *newlabs=gal_data_malloc_array(GAL_TYPE_INT32,
-                                         cltprm->numinitclumps+1, __func__,
-                                         "newlabs");
-
-  /* Initialize the new labels with CLUMPS_INIT (so the diffuse area can be
-     distinguished from the clumps). */
-  lf=(l=newlabs)+cltprm->numinitclumps+1; do *l++=CLUMPS_INIT; while(l<lf);
-
-
-  /* Set the new labels. Here we will also be removing clumps with a peak
-     that touches a river pixel. */
-  if(p->keepmaxnearriver)
+  size_t i, *s, *sf, *dinc;
+  float *sn = cltprm->sn ? cltprm->sn->array : NULL;
+  int32_t *l, *lf, *newlabs, curlab=1, *clabel=p->clabel->array;
+
+  /* If there were no clumps over the detection, then just set the number
+     of true clumps to zero, otherwise, see which ones should be
+     removed. */
+  if(cltprm->sn)
     {
-      for(i=1;i<cltprm->numinitclumps+1;++i)
-        if( sn[i] > p->clumpsnthresh ) newlabs[i]=curlab++;
-    }
-  else
-    {
-      for(i=1;i<cltprm->numinitclumps+1;++i)
+      /* Allocate the necessary arrays. */
+      newlabs=gal_data_malloc_array(GAL_TYPE_INT32,
+                                    cltprm->numinitclumps+1, __func__,
+                                    "newlabs");
+      dinc=gal_dimension_increment(ndim, dsize);
+
+      /* Initialize the new labels with CLUMPS_INIT (so the diffuse area
+         can be distinguished from the clumps). */
+      lf=(l=newlabs)+cltprm->numinitclumps+1;
+      do *l++=CLUMPS_INIT; while(l<lf);
+
+      /* Set the new labels. Here we will also be removing clumps with a peak
+         that touches a river pixel. */
+      if(p->keepmaxnearriver)
         {
-          /* Check if all the neighbors of this top element are touching a
-             river or not. */
-          istouching=0;
-          GAL_DIMENSION_NEIGHBOR_OP(cltprm->topinds[i], ndim, dsize, ndim,
-                                    dinc,
-                                    { if(clabel[nind]==0) istouching=1; });
-
-          /* If the peak isn't touching a river, then check its S/N and if
-             that is also good, give it a new label. */
-          if( !istouching && sn[i] > p->clumpsnthresh ) newlabs[i]=curlab++;
+          for(i=1;i<cltprm->numinitclumps+1;++i)
+            if( sn[i] > p->clumpsnthresh ) newlabs[i]=curlab++;
+        }
+      else
+        {
+          for(i=1;i<cltprm->numinitclumps+1;++i)
+            {
+              /* Check if all the neighbors of this top element are
+                 touching a river or not. */
+              istouching=0;
+              GAL_DIMENSION_NEIGHBOR_OP(cltprm->topinds[i], ndim, dsize,
+                                        ndim, dinc,
+                                        {
+                                          if(clabel[nind]==0)
+                                            istouching=1;
+                                        });
+
+              /* If the peak isn't touching a river, then check its S/N and
+                 if that is also good, give it a new label. */
+              if( !istouching && sn[i] > p->clumpsnthresh )
+                newlabs[i]=curlab++;
+            }
         }
-    }
-
-
-  /* Save the total number of true clumps in this detection. */
-  cltprm->numtrueclumps=curlab-1;
-
 
-  /* Correct the clump labels. Note that the non-clumpy regions over the
-     detections (rivers) have already been initialized to CLUMPS_INIT
-     (which is negative). So we'll just need to correct the ones with a
-     value larger than 0. */
-  sf=(s=cltprm->indexs->array)+cltprm->indexs->size;
-  do if(clabel[*s]>0) clabel[*s] = newlabs[ clabel[*s] ]; while(++s<sf);
+      /* Correct the clump labels. Note that the non-clumpy regions over the
+         detections (rivers) have already been initialized to CLUMPS_INIT
+         (which is negative). So we'll just need to correct the ones with a
+         value larger than 0. */
+      sf=(s=cltprm->indexs->array)+cltprm->indexs->size;
+      do if(clabel[*s]>0) clabel[*s] = newlabs[ clabel[*s] ]; while(++s<sf);
 
+      /* Save the total number of true clumps in this detection. */
+      cltprm->numtrueclumps=curlab-1;
 
-  /* Clean up. */
-  free(dinc);
-  free(newlabs);
+      /* Clean up. */
+      free(dinc);
+      free(newlabs);
+    }
+  else cltprm->numtrueclumps=0;
 }
diff --git a/bin/noisechisel/ui.c b/bin/noisechisel/ui.c
index 69a7c88..5f634c1 100644
--- a/bin/noisechisel/ui.c
+++ b/bin/noisechisel/ui.c
@@ -330,7 +330,7 @@ ui_set_output_names(struct noisechiselparams *p)
   if(output)
     {
       /* Delete the file if it already exists. */
-      gal_checkset_check_remove_file(p->cp.output, 0, p->cp.dontdelete);
+      gal_checkset_writable_remove(p->cp.output, 0, p->cp.dontdelete);
 
       /* When the output name is given (possibly with directory
          information), the check images will also be put in that same
diff --git a/bin/warp/ui.c b/bin/warp/ui.c
index 3ecbf1a..898f118 100644
--- a/bin/warp/ui.c
+++ b/bin/warp/ui.c
@@ -867,7 +867,7 @@ ui_preparations(struct warpparams *p)
      which we will need to determine the suffix if no output name is
      specified. */
   if(p->cp.output)
-    gal_checkset_check_remove_file(p->cp.output, 0, p->cp.dontdelete);
+    gal_checkset_writable_remove(p->cp.output, 0, p->cp.dontdelete);
   else
     p->cp.output=gal_checkset_automatic_output(&p->cp, p->inputname,
                                                ui_set_suffix(p));
diff --git a/doc/announce-acknowledge.txt b/doc/announce-acknowledge.txt
index b4c0c94..20169f3 100644
--- a/doc/announce-acknowledge.txt
+++ b/doc/announce-acknowledge.txt
@@ -2,9 +2,11 @@ This file is meant to keep the names of the people who's help 
must be
 acknowledged in the next release.
 
 Marjan Akbari
+Fernando Buitrago
 Adrian Bunk
 Antonio Diaz Diaz
 Mosè Giordano
+Stephen Hamer
 Raúl Infante Sainz
 Aurélien Jarno
 Alan Lefor
diff --git a/doc/gnuastro.texi b/doc/gnuastro.texi
index 54dec63..b6c95a1 100644
--- a/doc/gnuastro.texi
+++ b/doc/gnuastro.texi
@@ -1544,14 +1544,14 @@ management of its version controlled source server 
there.
 @c To the developers: please keep this in the same order as the THANKS file
 @c (alphabetical, except for the names in the paragraph above).
 We would also like to gratefully thank (in alphabetical order by family
-name) Marjan Akbari, Roland Bacon, Nicolas Bouch@'e, Adrian Bunk, Rosa
-Calvi, Antonio Diaz Diaz, Raúl Infante Sainz, Lee Kelvin, Mohammad-Reza
-Khellat, Alan Lefor, Guillaume Mahler, Francesco Montanari, William Pence,
-Yahya Sefidbakht, Ole Streicher, Ignacio Trujillo, David Valls-Gabaud and
-Christopher Willmer for their useful and constructive comments and
-suggestions. Finally we should thank all the (sometimes anonymous) people
-in various online forums which patiently answered all our small (but
-important) technical questions.
+name) Marjan Akbari, Roland Bacon, Nicolas Bouch@'e, Fernando Buitrago,
+Adrian Bunk, Rosa Calvi, Antonio Diaz Diaz, Stephen Hamer, Raúl Infante
+Sainz, Lee Kelvin, Mohammad-Reza Khellat, Alan Lefor, Guillaume Mahler,
+Francesco Montanari, William Pence, Yahya Sefidbakht, Ole Streicher,
+Ignacio Trujillo, David Valls-Gabaud and Christopher Willmer for their
+useful and constructive comments and suggestions. Finally we should thank
+all the (sometimes anonymous) people in various online forums which
+patiently answered all our small (but important) technical questions.
 
 All work on Gnuastro has been voluntary, but the authors are most grateful
 to the following institutions (in chronological order) for hosting us in
diff --git a/lib/checkset.c b/lib/checkset.c
index 7a8ac5d..4096a07 100644
--- a/lib/checkset.c
+++ b/lib/checkset.c
@@ -151,6 +151,67 @@ gal_checkset_allocate_copy_set(char *arg, char **copy, int 
*set)
 /**************************************************************/
 /********** Set file names and check if they exist ************/
 /**************************************************************/
+/* Given a filename, this function will separate its directory name
+   part. */
+char *
+gal_checkset_dir_part(char *filename)
+{
+  char *out;
+  size_t i, l=strlen(filename);
+
+  /* Find the first slash from the end. */
+  for(i=l;i!=0;--i)
+    if(filename[i]=='/')
+      break;
+
+  /* If there was no slash, then the current directory should be
+     given: */
+  if(i==0 && filename[0]!='/')
+    gal_checkset_allocate_copy("./", &out);
+  else
+    {
+      gal_checkset_allocate_copy(filename, &out);
+      out[i+1]='\0';
+    }
+
+  return out;
+}
+
+
+
+
+
+/* Given a file name, keep the non-directory part. Note that if there
+   is no forward slash in the input name, the full input name is
+   considered to be the notdir output.*/
+char *
+gal_checkset_not_dir_part(char *filename)
+{
+  size_t i, l;
+  char *out, *tmp=filename;
+
+  /* Find the first `/' to identify the directory */
+  l=strlen(filename);
+  for(i=l;i!=0;--i)
+    if(filename[i]=='/')
+      { tmp=&filename[i+1]; break; }
+
+  /* Get the length of the notdir name: */
+  l=strlen(tmp);
+  errno=0;
+  out=malloc((l+1)*sizeof *out);
+  if(out==NULL)
+    error(EXIT_FAILURE, errno, "%s: %zu bytes for notdir", __func__,
+          (l+1)*sizeof *out);
+
+  strcpy(out, tmp);
+  return out;
+}
+
+
+
+
+
 /* Check if a file exists and report if it doesn't: */
 void
 gal_checkset_check_file(char *filename)
@@ -200,8 +261,9 @@ gal_checkset_check_file_report(char *filename)
    won't be deleted, but the program will abort with an error, informing
    the user that the output can't be made. */
 void
-gal_checkset_check_remove_file(char *filename, int keep, int dontdelete)
+gal_checkset_writable_remove(char *filename, int keep, int dontdelete)
 {
+  char *dir;
   FILE *tmpfile;
 
   /* If the filename is `NULL' everything is ok (it doesn't exist)! In some
@@ -237,11 +299,23 @@ gal_checkset_check_remove_file(char *filename, int keep, 
int dontdelete)
             error(EXIT_FAILURE, errno, "%s", filename);
         }
     }
-  /* If the file doesn't exist, there is no problem, we wanted to
-     remove it any way! Any other kind of error should not be
-     tolerated! */
-  else if(errno!=ENOENT)
-    error(EXIT_FAILURE, errno, "%s", filename);
+
+  /* If the file doesn't exist, we just need to make sure if we have write
+     permissions to its host directory. */
+  else
+    {
+      /* Separate the directory part of the filename. */
+      dir=gal_checkset_dir_part(filename);
+
+      /* Make sure this directory is writable by this user. */
+      errno=0;
+      if( access(dir, W_OK) )
+        error(EXIT_FAILURE, errno, "cannot create any file(s) in the "
+              "directory `%s'", dir);
+
+      /* Clean up. */
+      free(dir);
+    }
 }
 
 
@@ -292,7 +366,7 @@ gal_checkset_dir_0_file_1(char *name, int dontdelete)
     return 0;
   else if (S_ISREG(nameinfo.st_mode))  /* It is a file, GOOD. */
     {
-      gal_checkset_check_remove_file(name, 0, dontdelete);
+      gal_checkset_writable_remove(name, 0, dontdelete);
       return 1;
     }
   else                                 /* Not a file or a dir, ABORT */
@@ -378,7 +452,7 @@ gal_checkset_automatic_output(struct 
gal_options_common_params *cp,
     }
 
   /* Remove the created filename if it already exits. */
-  gal_checkset_check_remove_file(out, cp->keep, cp->dontdelete);
+  gal_checkset_writable_remove(out, cp->keep, cp->dontdelete);
 
   /* Return the resulting filename. */
   return out;
@@ -388,80 +462,6 @@ gal_checkset_automatic_output(struct 
gal_options_common_params *cp,
 
 
 
-/* Given a filename, this function will separate its directory name
-   part. */
-char *
-gal_checkset_dir_part(char *input)
-{
-  char *out;
-  size_t i, l;
-
-  /* Find the first slash. */
-  l=strlen(input);
-  for(i=l;i!=0;--i)
-    if(input[i]=='/')
-      break;
-
-  /* If there was no slash, then the current directory should be
-     given: */
-  if(i==0)
-    {
-      errno=0;
-      out=malloc(3*sizeof *out);
-      if(out==NULL)
-        error(EXIT_FAILURE, errno, "%s: %zu bytes for current directory name",
-              __func__, 3*sizeof *out);
-      strcpy(out, "./");
-    }
-  else
-    {
-      errno=0;
-      out=malloc((l+1)*sizeof *out);
-      if(out==NULL)
-        error(EXIT_FAILURE, errno, "%s: %zu bytes for `out'", __func__,
-              (l+1)*sizeof *out);
-      strcpy(out, input);
-      out[i+1]='\0';
-    }
-
-  return out;
-}
-
-
-
-
-
-/* Given a file name, keep the non-directory part. Note that if there
-   is no forward slash in the input name, the full input name is
-   considered to be the notdir output.*/
-char *
-gal_checkset_not_dir_part(char *input)
-{
-  size_t i, l;
-  char *out, *tmp=input;
-
-  /* Find the first `/' to identify the directory */
-  l=strlen(input);
-  for(i=l;i!=0;--i)
-    if(input[i]=='/')
-      { tmp=&input[i+1]; break; }
-
-  /* Get the length of the notdir name: */
-  l=strlen(tmp);
-  errno=0;
-  out=malloc((l+1)*sizeof *out);
-  if(out==NULL)
-    error(EXIT_FAILURE, errno, "%s: %zu bytes for notdir", __func__,
-          (l+1)*sizeof *out);
-
-  strcpy(out, tmp);
-  return out;
-}
-
-
-
-
-
 /* Check if dirname is actually a real directory and that we can
    actually write inside of it. To insure all conditions an actual
    file will be made */
diff --git a/lib/fits.c b/lib/fits.c
index 9350c2f..9df4228 100644
--- a/lib/fits.c
+++ b/lib/fits.c
@@ -675,7 +675,53 @@ gal_fits_hdu_open(char *filename, char *hdu, int iomode)
 
   /* Open the FITS file: */
   if( fits_open_file(&fptr, ffname, iomode, &status) )
-    gal_fits_io_error(status, "reading this FITS file");
+    {
+      switch(status)
+        {
+        /* Since the default HDU is `1', when the file only has one
+           extension, this error is common, so we will put a special
+           notice. */
+        case END_OF_FILE:
+          if( hdu[0]=='1' && hdu[1]=='\0' )
+            error(EXIT_FAILURE, 0, "%s has only one extension/HDU but you "
+                  "have asked for the second HDU (hdu number 1 in CFITSIO)."
+                  "\n\n"
+                  "To fix the problem please add `--hdu=0' (or `-h0') to "
+                  "your command when calling Gnuastro's programs. For "
+                  "library users, please give a value of \"0\" to the HDU "
+                  "argument.\n\n"
+                  "FOOTNOTE -- When writing a new FITS file, Gnuastro leaves "
+                  "the first HDU blank (with no data) and writes the "
+                  "outputs in the second HDU. In this way the keywords of "
+                  "the the first HDU can be used as meta data of the whole "
+                  "file (which may contain many extensions). This is the "
+                  "recommended way in the FITS standard. As a result, "
+                  "Gnuastro's default HDU to read an extension in a FITS "
+                  "file is the second. This error is commonly caused when "
+                  "the FITS file wasn't created according to this "
+                  "convention.", filename);
+          break;
+
+        /* Generic error below is fine for this case */
+        case BAD_HDU_NUM:
+          break;
+
+        /* In case an un-expected error occurs, use the general CFITSIO
+           reporting that we have already prepared. */
+        default:
+          gal_fits_io_error(status, "opening the given extension/HDU in "
+                            "the given file");
+        }
+
+      error(EXIT_FAILURE, 0, "%s: extension/HDU `%s' doesn't exist. Please "
+            "run the following command to see the extensions/HDUs in "
+            "`%s':\n\n"
+            "    $ astfits %s\n\n"
+            "The respective HDU number (or name, when present) may be used "
+            "with the `--hdu' option in Gnuastro's programs (or the `hdu' "
+            "argument in Gnuastro's libraries) to open the respective HDU.",
+            filename, hdu, filename, filename);
+    }
 
   /* Clean up and the pointer. */
   free(ffname);
@@ -2571,7 +2617,7 @@ gal_fits_tab_write(gal_data_t *cols, gal_list_str_t 
*comments,
 
 
   /* Remove the output if it already exists. */
-  gal_checkset_check_remove_file(filename, 0, dontdelete);
+  gal_checkset_writable_remove(filename, 0, dontdelete);
 
 
   /* Create the FITS file */
diff --git a/lib/gnuastro-internal/checkset.h b/lib/gnuastro-internal/checkset.h
index 43a6ed6..2bf63a3 100644
--- a/lib/gnuastro-internal/checkset.h
+++ b/lib/gnuastro-internal/checkset.h
@@ -85,6 +85,12 @@ gal_checkset_allocate_copy_set(char *arg, char **copy, int 
*set);
 /**************************************************************/
 /********** Set file names and check if they exist ************/
 /**************************************************************/
+char *
+gal_checkset_dir_part(char *filename);
+
+char *
+gal_checkset_not_dir_part(char *filename);
+
 void
 gal_checkset_check_file(char *filename);
 
@@ -92,7 +98,7 @@ int
 gal_checkset_check_file_report(char *filename);
 
 void
-gal_checkset_check_remove_file(char *filename, int keep, int dontdelete);
+gal_checkset_writable_remove(char *filename, int keep, int dontdelete);
 
 int
 gal_checkset_dir_0_file_1(char *name, int dontdelete);
@@ -101,12 +107,6 @@ char *
 gal_checkset_automatic_output(struct gal_options_common_params *cp,
                               char *inname, char *suffix);
 
-char *
-gal_checkset_dir_part(char *input);
-
-char *
-gal_checkset_not_dir_part(char *input);
-
 void
 gal_checkset_check_dir_write_add_slash(char **dirname);
 
diff --git a/lib/options.c b/lib/options.c
index 3f0277b..b7ac93d 100644
--- a/lib/options.c
+++ b/lib/options.c
@@ -1889,7 +1889,7 @@ options_print_all(struct gal_options_common_params *cp, 
char *dirname,
       asprintf(&filename, "%s/%s.conf", dirname, cp->program_exec);
 
       /* Remove the file if it already exists. */
-      gal_checkset_check_remove_file(filename, 0, 0);
+      gal_checkset_writable_remove(filename, 0, 0);
 
       /* Open the file for writing */
       errno=0;
diff --git a/lib/txt.c b/lib/txt.c
index 32f9578..5e0ecf0 100644
--- a/lib/txt.c
+++ b/lib/txt.c
@@ -1155,7 +1155,7 @@ txt_open_file_write_info(gal_data_t *datall, char **fmts,
 
 
   /* Check the file and open it. */
-  gal_checkset_check_remove_file(filename, 0, dontdelete);
+  gal_checkset_writable_remove(filename, 0, dontdelete);
   errno=0;
   fp=fopen(filename, "w");
   if(fp==NULL)



reply via email to

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