gnuastro-commits
[Top][All Lists]
Advanced

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

[gnuastro-commits] master 05c660a 3/9: Library: new ds9.h library functi


From: Mohammad Akhlaghi
Subject: [gnuastro-commits] master 05c660a 3/9: Library: new ds9.h library functions for parsing ds9 files
Date: Fri, 21 May 2021 23:39:17 -0400 (EDT)

branch: master
commit 05c660a8ee596be96a95453295370399dbc5bef8
Author: Mohammad Akhlaghi <mohammad@akhlaghi.org>
Commit: Mohammad Akhlaghi <mohammad@akhlaghi.org>

    Library: new ds9.h library functions for parsing ds9 files
    
    Until now, there was only a single 'ui_polygon_from_ds9_reg' function in
    the Crop program for reading a DS9 region file. However, other programs
    (like Table) also have this feature (and would thus need this
    function). Also, generally, there are more operations that can be done on
    DS9 region files or other types of ds9 output files.
    
    With this commit, that function has been generalized into a new library
    file called ('lib/ds9.c', with its corresponding 'lib/gnuastro/ds9.h'
    header). Its calling with the crop program has also been correspondingly
    corrected.
---
 bin/crop/ui.c      | 154 ++++++++++++----------------------------------------
 lib/Makefile.am    |  20 +++----
 lib/ds9.c          | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/gnuastro/ds9.h |  74 +++++++++++++++++++++++++
 4 files changed, 273 insertions(+), 131 deletions(-)

diff --git a/bin/crop/ui.c b/bin/crop/ui.c
index f6f6fa8..b6f4e2e 100644
--- a/bin/crop/ui.c
+++ b/bin/crop/ui.c
@@ -28,6 +28,7 @@ along with Gnuastro. If not, see 
<http://www.gnu.org/licenses/>.
 #include <stdio.h>
 #include <string.h>
 
+#include <gnuastro/ds9.h>
 #include <gnuastro/wcs.h>
 #include <gnuastro/list.h>
 #include <gnuastro/fits.h>
@@ -269,119 +270,45 @@ ui_parse_coordinate_mode(struct argp_option *option, 
char *arg,
 /**************************************************************/
 /***************       Sanity Check         *******************/
 /**************************************************************/
+
+/* Do polygon-related sanity checks that can be very low-level. */
 static void
-ui_polygon_from_ds9_reg(struct cropparams *p)
+ui_check_polygon_from_ds9(struct cropparams *p)
 {
-  FILE *fp;
-  char *polygonstr;
-  size_t commacounter=0;
-  int coordmode=IMGCROP_MODE_INVALID;
-  size_t plinelen, linesize=10, lineno=0;
-  char *c, *line, *ds9regstart="# Region file format: DS9";
-  char *polygonformaterr="It is expected for the line to have "
-    "this format: 'polygon(AAA,BBB,...)'. Where 'AAA' and 'BBB' "
-    "are numbers and '...' signifies that any number of points "
-    "are possible";
-
-  /* Allocate size to the lines on the file and check if it was sucessfull.
-     The getline function reallocs the necessary memory. */
-  errno=0;
-  line = malloc(linesize * sizeof(*line));
-  if(line == NULL)
-    error(EXIT_FAILURE, errno, "%s: %zu bytes for line buffer",
-          __func__, linesize * sizeof(*line));
+  int ds9regmode;
 
-  /* Open the file and checks if it's not null. */
-  errno=0;
-  fp = fopen(p->polygonname, "r");
-  if(fp == NULL)
-    error(EXIT_FAILURE, errno, "The polygon file is blank");
-
-  /* Get the lines on the file. */
-  while(getline(&line, &linesize, fp)!=-1)
+  /* This is only relevant when a region file is actually given. */
+  if(p->polygonname)
     {
-      /* To have line-counters starting from 1. */
-      ++lineno;
-
-      /* The first line should start with a fixed string. */
-      if(lineno==1)
-        {
-          if( strncmp(line, ds9regstart, 25) )
-            error(EXIT_FAILURE, 0, "%s: doesn't appear to be a DS9 "
-                  "region file! We assume that DS9 region files begin "
-                  "with this string in their first line: '%s'",
-                  p->polygonname, ds9regstart);
-          continue;
-        }
-
-      /* If we are on the coordinate mode line, then set the mode of Crop
-         based on it. */
-      if( !strcmp(line, "fk5\n") || !strcmp(line, "image\n") )
+      /* These two options cannot be called together. */
+      if(p->polygon)
+        error(EXIT_FAILURE, errno, "'--polygon' and '--polygonname' "
+              "cannot be given together. With the first you specify the "
+              "polygon vertices directly on the command-line. With the "
+              "second, you give a DS9 region file and the polygon "
+              "vertices are read from that.");
+      else
         {
-          /* Make sure it hasn't been called more than once. */
-          if(coordmode!=IMGCROP_MODE_INVALID)
-            error_at_line(EXIT_FAILURE, 0, p->polygonname, lineno,
-                          "more than one coordinate line defined");
-
-          /* Set the proper mode. */
-          if(!strcmp(line, "fk5\n")) coordmode=IMGCROP_MODE_WCS;
-          else                       coordmode=IMGCROP_MODE_IMG;
-
-          /* Stop parsing the file if the polygon has also been found by
-             this point (we don't need any more information, no need to
-             waste the user's CPU and time). */
-          if(p->polygon) break;
+          /* Extract the polygon and the coordinate mode. */
+          p->polygon=gal_ds9_reg_read_polygon(p->polygonname,
+                                              &ds9regmode);
+          switch(ds9regmode)
+            {
+            case GAL_DS9_COORD_MODE_IMG: p->mode=IMGCROP_MODE_IMG; break;
+            case GAL_DS9_COORD_MODE_WCS: p->mode=IMGCROP_MODE_WCS; break;
+            default:
+              error(EXIT_FAILURE, 0, "%s: a bug! Please contact us at "
+                    "'%s' to fix the problem. The output coordinate mode "
+                    "of 'gal_ds9_reg_read_polygon' (%d) isn't recognized "
+                    "by this function", __func__, PACKAGE_BUGREPORT,
+                    ds9regmode);
+            }
         }
 
-      /* The line containing the polygon information starts with
-         'polygon('. */
-      if( !strncmp(line, "polygon(", 8) )
-        {
-          /* Get the line length and check if it is indeed in the proper
-             format. If so, remove the last parenthesis. */
-          plinelen=strlen(line);
-          if(line[plinelen-2]==')')
-            line[plinelen-2]='\0';
-          else
-            error_at_line(EXIT_FAILURE, 0, p->polygonname, lineno,
-                          "line with polygon vertices doesn't end "
-                          "with ')'. %s", polygonformaterr);
-
-          /* Convert the string to the expected format (with ':' separating
-             each vertice). Note how we are ignoring the first 8 characters
-             that contain 'polygon('. */
-          polygonstr=&line[8];
-          for(c=polygonstr; *c!='\0'; ++c)
-            if(*c==',' && (++commacounter % 2) == 0 ) *c=':';
-
-          /* Read the coordinates within the line. */
-          p->polygon=gal_options_parse_colon_sep_csv_raw(polygonstr,
-                                                         p->polygonname,
-                                                         lineno);
-
-          /* Stop parsing the file if the coordinate mode has also been
-             found by this point (we don't need any more information, no
-             need to waste the user's CPU and time). */
-          if(coordmode!=IMGCROP_MODE_INVALID) break;
-        }
+      /* Clean up. */
+      free(p->polygonname);
+      p->polygonname=NULL;
     }
-
-  /* If no coordinate mode was found in the file, print an error. */
-  if(coordmode==IMGCROP_MODE_INVALID)
-    error(EXIT_FAILURE, 0, "%s: no coordinate mode found! "
-          "We expect one line to be either 'fk5' or 'image'",
-          p->polygonname);
-
-  /* If no polygon line was in the file, abort with an error. */
-  if(p->polygon==NULL)
-    error(EXIT_FAILURE, 0, "%s: no polygon statement found! We expect "
-          "one line in the format of 'polygon(AAA,BBB,...)' in the "
-          "file given to '--polygonname' option. %s", p->polygonname,
-          polygonformaterr);
-
-  /* Free the space used. */
-  free(line);
-  fclose(fp);
 }
 
 
@@ -399,22 +326,7 @@ ui_read_check_only_options(struct cropparams *p)
   /* If a DS9 region file should be used for the polygon, read it. This is
      done first for two reasons. 1) It can change the value of '--mode'. 2)
      It will set the '--polygon' option's value. */
-  if(p->polygonname)
-    {
-      if(p->polygon)
-        error(EXIT_FAILURE, errno, "'--polygon' and '--polygonname' "
-              "cannot be given together. With the first you specify the "
-              "polygon vertices directly on the command-line. With the "
-              "second, you give a DS9 region file and the polygon "
-              "vertices are read from that.");
-      else
-        {
-          ui_polygon_from_ds9_reg(p);
-          free(p->polygonname);
-          p->polygonname=NULL;
-        }
-    }
-
+  ui_check_polygon_from_ds9(p);
 
   /* Make sure that only one of the crop definitions is given. */
   checksum = ( (p->center!=NULL)
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 4b4b297..de1a311 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -70,7 +70,7 @@ libgnuastro_la_SOURCES = $(MAYBE_WCSDISTORTION) arithmetic.c \
   arithmetic-le.c arithmetic-lt.c arithmetic-minus.c arithmetic-modulo.c \
   arithmetic-multiply.c arithmetic-ne.c arithmetic-or.c \
   arithmetic-plus.c arithmetic-set.c array.c binary.c blank.c box.c \
-  checkset.c convolve.c cosmology.c data.c eps.c fits.c git.c \
+  checkset.c convolve.c cosmology.c data.c ds9.c eps.c fits.c git.c \
   interpolate.c jpeg.c kdtree.c label.c list.c match.c options.c pdf.c \
   permutation.c pointer.c polygon.c qsort.c dimension.c speclines.c \
   statistics.c table.c tableintern.c threads.c tiff.c tile.c \
@@ -87,15 +87,15 @@ headersdir=$(top_srcdir)/lib/gnuastro
 pkginclude_HEADERS = gnuastro/config.h $(headersdir)/arithmetic.h \
   $(headersdir)/array.h $(headersdir)/binary.h $(headersdir)/blank.h \
   $(headersdir)/box.h $(headersdir)/convolve.h $(headersdir)/cosmology.h \
-  $(headersdir)/data.h $(headersdir)/dimension.h $(headersdir)/eps.h \
-  $(headersdir)/fits.h $(headersdir)/git.h $(headersdir)/interpolate.h \
-  $(headersdir)/jpeg.h $(headersdir)/kdtree.h $(headersdir)/label.h \
-  $(headersdir)/list.h $(headersdir)/match.h $(headersdir)/pdf.h \
-  $(headersdir)/permutation.h $(headersdir)/pointer.h $(headersdir)/polygon.h \
-  $(headersdir)/qsort.h $(headersdir)/speclines.h $(headersdir)/statistics.h \
-  $(headersdir)/table.h $(headersdir)/threads.h $(headersdir)/tiff.h \
-  $(headersdir)/tile.h $(headersdir)/txt.h $(headersdir)/type.h \
-  $(headersdir)/units.h $(headersdir)/wcs.h
+  $(headersdir)/data.h $(headersdir)/dimension.h $(headersdir)/ds9.h \
+  $(headersdir)/eps.h $(headersdir)/fits.h $(headersdir)/git.h \
+  $(headersdir)/interpolate.h $(headersdir)/jpeg.h $(headersdir)/kdtree.h \
+  $(headersdir)/label.h $(headersdir)/list.h $(headersdir)/match.h \
+  $(headersdir)/pdf.h $(headersdir)/permutation.h $(headersdir)/pointer.h \
+  $(headersdir)/polygon.h $(headersdir)/qsort.h $(headersdir)/speclines.h \
+  $(headersdir)/statistics.h $(headersdir)/table.h $(headersdir)/threads.h \
+  $(headersdir)/tiff.h $(headersdir)/tile.h $(headersdir)/txt.h \
+  $(headersdir)/type.h $(headersdir)/units.h $(headersdir)/wcs.h
 
 
 
diff --git a/lib/ds9.c b/lib/ds9.c
new file mode 100644
index 0000000..9fb6155
--- /dev/null
+++ b/lib/ds9.c
@@ -0,0 +1,156 @@
+/*********************************************************************
+Functions to interface with DS9 files.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Mohammad Akhlaghi <mohammad@akhlaghi.org>
+Contributing author(s):
+Copyright (C) 2015-2021, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+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>
+
+#include <gnuastro/ds9.h>
+#include <gnuastro/data.h>
+
+#include <gnuastro-internal/options.h>
+
+
+/* Read the polygon specified in the given DS9 region file and parse it in
+   the standard format. */
+gal_data_t *
+gal_ds9_reg_read_polygon(char *filename, int *coordmode)
+{
+  FILE *fp;
+  char *polygonstr;
+  gal_data_t *out=NULL;
+  size_t commacounter=0;
+  size_t plinelen, linesize=10, lineno=0;
+  char *c, *line, *ds9regstart="# Region file format: DS9";
+  char *polygonformaterr="It is expected for the line to have "
+    "this format: 'polygon(AAA,BBB,...)'. Where 'AAA' and 'BBB' "
+    "are numbers and '...' signifies that any number of points "
+    "are possible";
+
+  /* Initialize 'coordmode'. */
+  *coordmode=GAL_DS9_COORD_MODE_INVALID;
+
+  /* Allocate size to the lines on the file and check if it was sucessfull.
+     The getline function reallocs the necessary memory. */
+  errno=0;
+  line = malloc(linesize * sizeof(*line));
+  if(line == NULL)
+    error(EXIT_FAILURE, errno, "%s: %zu bytes for line buffer",
+          __func__, linesize * sizeof(*line));
+
+  /* Open the file and checks if it's not null. */
+  errno=0;
+  fp = fopen(filename, "r");
+  if(fp == NULL)
+    error(EXIT_FAILURE, errno, "The polygon file is blank");
+
+  /* Get the lines on the file. */
+  while(getline(&line, &linesize, fp)!=-1)
+    {
+      /* To have line-counters starting from 1. */
+      ++lineno;
+
+      /* The first line should start with a fixed string. */
+      if(lineno==1)
+        {
+          if( strncmp(line, ds9regstart, 25) )
+            error(EXIT_FAILURE, 0, "%s: doesn't appear to be a DS9 "
+                  "region file! We assume that DS9 region files begin "
+                  "with this string in their first line: '%s'",
+                  filename, ds9regstart);
+          continue;
+        }
+
+      /* If we are on the coordinate mode line, then set the mode of Crop
+         based on it. */
+      if( !strcmp(line, "fk5\n") || !strcmp(line, "image\n") )
+        {
+          /* Make sure it hasn't been called more than once. */
+          if(*coordmode!=GAL_DS9_COORD_MODE_INVALID)
+            error_at_line(EXIT_FAILURE, 0, filename, lineno,
+                          "more than one coordinate line defined");
+
+          /* Set the proper mode. */
+          if(!strcmp(line, "fk5\n")) *coordmode=GAL_DS9_COORD_MODE_WCS;
+          else                       *coordmode=GAL_DS9_COORD_MODE_IMG;
+
+          /* Stop parsing the file if the polygon has also been found by
+             this point (we don't need any more information, no need to
+             waste the user's CPU and time). */
+          if(out) break;
+        }
+
+      /* The line containing the polygon information starts with
+         'polygon('. */
+      if( !strncmp(line, "polygon(", 8) )
+        {
+          /* Get the line length and check if it is indeed in the proper
+             format. If so, remove the last parenthesis. */
+          plinelen=strlen(line);
+          if(line[plinelen-2]==')')
+            line[plinelen-2]='\0';
+          else
+            error_at_line(EXIT_FAILURE, 0, filename, lineno,
+                          "line with polygon vertices doesn't end "
+                          "with ')'. %s", polygonformaterr);
+
+          /* Convert the string to the expected format (with ':' separating
+             each vertice). Note how we are ignoring the first 8 characters
+             that contain 'polygon('. */
+          polygonstr=&line[8];
+          for(c=polygonstr; *c!='\0'; ++c)
+            if(*c==',' && (++commacounter % 2) == 0 ) *c=':';
+
+          /* Read the coordinates within the line. */
+          out=gal_options_parse_colon_sep_csv_raw(polygonstr,
+                                                  filename,
+                                                  lineno);
+
+          /* Stop parsing the file if the coordinate mode has also been
+             found by this point (we don't need any more information, no
+             need to waste the user's CPU and time). */
+          if(*coordmode!=GAL_DS9_COORD_MODE_INVALID) break;
+        }
+    }
+
+  /* If no coordinate mode was found in the file, print an error. */
+  if(*coordmode==GAL_DS9_COORD_MODE_INVALID)
+    error(EXIT_FAILURE, 0, "%s: no coordinate mode found! "
+          "We expect one line to be either 'fk5' or 'image'",
+          filename);
+
+  /* If no polygon line was in the file, abort with an error. */
+  if(out==NULL)
+    error(EXIT_FAILURE, 0, "%s: no polygon statement found! We expect "
+          "one line in the format of 'polygon(AAA,BBB,...)' in the "
+          "file given to '--polygonname' option. %s", filename,
+          polygonformaterr);
+
+  /* Clean up and return. */
+  free(line);
+  fclose(fp);
+  return out;
+}
diff --git a/lib/gnuastro/ds9.h b/lib/gnuastro/ds9.h
new file mode 100644
index 0000000..41e5719
--- /dev/null
+++ b/lib/gnuastro/ds9.h
@@ -0,0 +1,74 @@
+/*********************************************************************
+Functions to interface with DS9 files.
+This is part of GNU Astronomy Utilities (Gnuastro) package.
+
+Original author:
+     Mohammad Akhlaghi <mohammad@akhlaghi.org>
+Contributing author(s):
+Copyright (C) 2015-2021, Free Software Foundation, Inc.
+
+Gnuastro is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation, either version 3 of the License, or (at your
+option) any later version.
+
+Gnuastro is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Gnuastro. If not, see <http://www.gnu.org/licenses/>.
+**********************************************************************/
+#ifndef __GAL_DS9_H__
+#define __GAL_DS9_H__
+
+/* Include other headers if necessary here. Note that other header files
+   must be included before the C++ preparations below */
+
+#include <gnuastro/data.h>
+
+/* C++ Preparations */
+#undef __BEGIN_C_DECLS
+#undef __END_C_DECLS
+#ifdef __cplusplus
+# define __BEGIN_C_DECLS extern "C" {
+# define __END_C_DECLS }
+#else
+# define __BEGIN_C_DECLS                /* empty */
+# define __END_C_DECLS                  /* empty */
+#endif
+/* End of C++ preparations */
+
+
+
+/* Actual header contants (the above were for the Pre-processor). */
+__BEGIN_C_DECLS  /* From C++ preparations */
+
+
+
+
+
+/* Modes to interpret coordinates. */
+enum gal_ds9_coord_modes
+{
+  GAL_DS9_COORD_MODE_INVALID,         /* For sanity checks.     */
+
+  GAL_DS9_COORD_MODE_IMG,             /* Image coordinates. */
+  GAL_DS9_COORD_MODE_WCS,             /* WCS coordinates.   */
+};
+
+
+
+
+
+gal_data_t *
+gal_ds9_reg_read_polygon(char *filename, int *coordmode);
+
+
+
+
+
+__END_C_DECLS    /* From C++ preparations */
+
+#endif           /* __GAL_WCS_H__ */



reply via email to

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