summaryrefslogtreecommitdiff
path: root/src/silx/io/specfile/src/sflabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/silx/io/specfile/src/sflabel.c')
-rw-r--r--src/silx/io/specfile/src/sflabel.c658
1 files changed, 658 insertions, 0 deletions
diff --git a/src/silx/io/specfile/src/sflabel.c b/src/silx/io/specfile/src/sflabel.c
new file mode 100644
index 0000000..29e8f57
--- /dev/null
+++ b/src/silx/io/specfile/src/sflabel.c
@@ -0,0 +1,658 @@
+# /*##########################################################################
+# Copyright (C) 1995-2022 European Synchrotron Radiation Facility
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ############################################################################*/
+/************************************************************************
+ *
+ * File: sflabel.c
+ *
+ * Project: SpecFile library
+ *
+ * Description: Access to labels and motors
+ *
+ * Author: V.Rey
+ *
+ * Date: $Date: 2003/02/03 13:15:35 $
+ *
+ ************************************************************************/
+/*
+ * Log:
+ * $Log: sflabel.c,v $
+ * Revision 1.3 2003/02/03 13:15:35 rey
+ * Small change in handling of empty spaces at the beginning of the label buffer
+ *
+ * Revision 1.2 2002/11/20 09:56:31 sole
+ * Some macros leave more than 1 space between #L and the first label.
+ * Routine modified to be able to deal with already collected data.
+ * The offending macro(s) should be re-written.
+ *
+ * Revision 1.1 2002/11/20 08:21:34 sole
+ * Initial revision
+ *
+ * Revision 3.0 2000/12/20 14:17:19 rey
+ * Python version available
+ *
+ * Revision 2.2 2000/12/20 12:12:08 rey
+ * bug corrected with SfAllMotors
+ *
+ * Revision 2.1 2000/07/31 19:05:10 19:05:10 rey (Vicente Rey-Bakaikoa)
+ * SfUpdate and bug corrected in ReadIndex
+ *
+ * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa)
+ * New version of the library. Complete rewrite
+ * Adds support for MCA
+ */
+#include <SpecFile.h>
+#include <SpecFileP.h>
+#include <locale_management.h>
+#ifndef _GNU_SOURCE
+#ifdef PYMCA_POSIX
+#include <locale.h>
+#endif
+#endif
+
+/*
+ * Declarations
+ */
+DllExport char * SfLabel ( SpecFile *sf, long index, long column,
+ int *error );
+DllExport long SfAllLabels ( SpecFile *sf, long index, char ***labels,
+ int *error );
+DllExport char * SfMotor ( SpecFile *sf, long index, long number,
+ int *error );
+DllExport long SfAllMotors ( SpecFile *sf, long index, char ***names,
+ int *error );
+DllExport double SfMotorPos ( SpecFile *sf, long index, long number,
+ int *error );
+DllExport double SfMotorPosByName( SpecFile *sf, long index, char *name,
+ int *error );
+DllExport long SfAllMotorPos ( SpecFile *sf, long index, double **pos,
+ int *error );
+
+
+#define BUFFER_SIZE 256
+#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
+
+
+/*********************************************************************
+ * Function: char *SfLabel( sf, index, column, error )
+ *
+ * Description: Reads one label.
+ *
+ * Parameters:
+ * Input : (1) SpecScan pointer
+ * (2) Scan index
+ * (3) Column number
+ * Output: (4) Error number
+ * Returns:
+ * Pointer to the label ,
+ * or NULL if errors occured.
+ * Possible errors:
+ * SF_ERR_MEMORY_ALLOC | => getStrFromArr()
+ * SF_ERR_LABEL_NOT_FOUND
+ * SF_ERR_LINE_EMPTY |
+ * SF_ERR_LINE_NOT_FOUND |
+ * SF_ERR_SCAN_NOT_FOUND | => SfAllLabels()
+ * SF_ERR_FILE_READ |
+ *
+ * Remark: The memory allocated should be freed by the application
+ *
+ *********************************************************************/
+DllExport char *
+SfLabel( SpecFile *sf, long index, long column, int *error )
+{
+
+ char **labels=NULL;
+ long no_labels;
+ char *label=NULL;
+ long selection;
+
+ if (sfSetCurrent(sf,index,error) == -1)
+ return((char *)NULL);
+
+ if (sf->no_labels != -1 ) {
+ no_labels = sf->no_labels;
+ } else {
+ no_labels = SfAllLabels(sf,index,&labels,error);
+ }
+
+ if (no_labels == 0 || no_labels == -1) return((char *)NULL);
+
+ if ( column < 0 ) {
+ selection = no_labels + column;
+ } else {
+ selection = column - 1;
+ }
+
+ if (selection < 0 || selection > no_labels - 1 ) {
+ *error = SF_ERR_COL_NOT_FOUND;
+ if (labels != (char **) NULL )
+ freeArrNZ((void ***)&labels,no_labels);
+ return((char *)NULL);
+ }
+
+ if (labels != (char **)NULL) {
+ label = (char *)strdup(labels[selection]);
+ freeArrNZ((void ***)&labels,no_labels);
+ } else {
+ label = (char *) strdup(sf->labels[selection]);
+ }
+ return( label );
+}
+
+
+/*********************************************************************
+ * Function: long SfAllLabels( sf, index, labels, error )
+ *
+ * Description: Reads all labels in #L lines
+ *
+ * Parameters:
+ * Input : (1) SpecScan pointer
+ * (2) Scan index
+ * Output: (3) Labels
+ * (4) Error number
+ * Returns:
+ * Number of labels
+ * ( -1 ) if error.
+ * Possible errors:
+ * SF_ERR_MEMORY_ALLOC ||=> cpyStrArr(),lines2words()
+ * SF_ERR_SCAN_NOT_FOUND | => SfHeader()
+ * SF_ERR_FILE_READ |
+ * SF_ERR_LINE_EMPTY
+ * SF_ERR_LINE_NOT_FOUND
+ * Remark: The memory allocated should be freed by the application
+ *
+ *********************************************************************/
+DllExport long
+SfAllLabels( SpecFile *sf, long index, char ***labels, int *error )
+{
+ static char tmplab[BUFFER_SIZE];
+
+ char **labarr;
+ char *onelabel;
+
+ char *ptr,
+ *buf=NULL;
+
+ long no_labels = 0;
+ short i;
+
+ /*
+ * select scan
+ */
+ if (sfSetCurrent(sf,index,error) == -1) {
+ *labels = NULL;
+ return(0);
+ }
+
+ /*
+ * Do not do it if already done
+ */
+ if (sf->labels != (char **)NULL ) {
+ labarr = (char **)malloc(sizeof(char *) * sf->no_labels);
+ for ( i=0;i<sf->no_labels;i++)
+ labarr[i] = (char *)strdup(sf->labels[i]);
+ *labels = labarr;
+ return(sf->no_labels);
+ }
+
+ /*
+ * else..
+ */
+ if (sfGetHeaderLine(sf,FROM_SCAN,SF_LABEL,&buf,error) == -1) {
+ *labels = NULL;
+ return(0);
+ }
+
+ if ( buf[0] == '\0') {
+ *labels = NULL;
+ return(0);
+ }
+
+ if ( (labarr = (char **)malloc( sizeof(char *))) == (char **)NULL) {
+ *error = SF_ERR_MEMORY_ALLOC;
+ return(-1);
+ }
+
+ no_labels = 0;
+ i = 0;
+
+ /*
+ * avoid problem of having too many spaces at the beginning
+ * with bad written macros -> added check for empty string
+ *
+ * get rid of spaces at the beginning of the string buffer
+ */
+
+ ptr = buf;
+ while((ptr < buf + strlen(buf) -1) && (*ptr == ' ')) ptr++;
+
+ for (i=0;ptr < buf + strlen(buf) -1;ptr++,i++) {
+ if (*ptr==' ' && *(ptr+1) == ' ') { /* two spaces delimits one label */
+ tmplab[MIN(i, BUFFER_SIZE-1)] = '\0';
+
+ labarr = (char **)realloc( labarr, (no_labels+1) * sizeof(char *));
+ onelabel = (char *) malloc (i+2);
+ strcpy(onelabel,tmplab);
+ labarr[no_labels] = onelabel;
+
+ no_labels++;
+ i=-1;
+ for(;*(ptr+1) == ' ' && ptr < buf+strlen(buf)-1;ptr++);
+ } else if (i < BUFFER_SIZE) {
+ tmplab[i] = *ptr;
+ }
+ }
+
+ if (*ptr != ' ') {
+ tmplab[i] = *ptr;
+ i++;
+ }
+ tmplab[i] = '\0';
+
+ labarr = (char **)realloc( labarr, (no_labels+1) * sizeof(char *));
+ onelabel = (char *) malloc (i+2);
+ strcpy(onelabel,tmplab);
+ labarr[no_labels] = onelabel;
+
+ no_labels++;
+
+ /*
+ * Save in specfile structure
+ */
+ sf->no_labels = no_labels;
+ sf->labels = (char **) malloc( sizeof(char *) * no_labels);
+ for (i=0;i<no_labels;i++)
+ sf->labels[i] = (char *) strdup(labarr[i]);
+
+ *labels = labarr;
+ return( no_labels );
+}
+
+
+/*********************************************************************
+ * Function: long SfAllMotors( sf, index, names, error )
+ *
+ * Description: Reads all motor names in #O lines (in file header)
+ *
+ * Parameters:
+ * Input : (1) SpecScan pointer
+ * (2) Scan index
+ * Output: (3) Names
+ * (4) Error number
+ * Returns:
+ * Number of found names
+ * ( -1 ) if errors.
+ * Possible errors:
+ * SF_ERR_SCAN_NOT_FOUND
+ * SF_ERR_LINE_NOT_FOUND
+ * SF_ERR_LINE_EMPTY
+ * SF_ERR_MEMORY_ALLOC || => cpyStrArr(),lines2words()
+ * SF_ERR_FILE_READ |
+ * SF_ERR_HEADER_NOT_FOUND | => SfFileHeader()
+ *
+ * Remark: The memory allocated should be freed by the application
+ *
+ *********************************************************************/
+DllExport long
+SfAllMotors( SpecFile *sf, long index, char ***names, int *error )
+{
+ char **lines;
+ char *thisline,
+ *endline;
+
+ char **motarr;
+ char *onemot;
+
+ static char tmpmot[BUFFER_SIZE];
+
+ char *ptr;
+
+ long motct = 0;
+ long no_lines;
+ short i,j;
+
+ /*
+ * go to scan
+ */
+ if (sfSetCurrent(sf,index,error) == -1) {
+ *names = NULL;
+ return(0);
+ }
+
+ /*
+ * if motor names for this scan have already been read
+ */
+ if (sf->motor_names != (char **)NULL) {
+ motarr = (char **)malloc(sizeof(char *) * sf->no_motor_names);
+ for (i=0;i<sf->no_motor_names;i++) {
+ motarr[i] = (char *) strdup (sf->motor_names[i]);
+ }
+ *names = motarr;
+ return(sf->no_motor_names);
+ }
+
+ /*
+ * else
+ */
+ no_lines = SfHeader(sf, index,"O",&lines,error);
+ if (no_lines == -1 || no_lines == 0 ) {
+ *names = (char **) NULL;
+ return(-1);
+ }
+
+ if ( (motarr = (char **)malloc( sizeof(char *))) == (char **)NULL) {
+ *error = SF_ERR_MEMORY_ALLOC;
+ return(-1);
+ }
+
+ motct = 0;
+
+ for (j=0;j<no_lines;j++) {
+ thisline = lines[j] + 4;
+ endline = thisline + strlen(thisline);
+ for(ptr=thisline;*ptr == ' ';ptr++);
+ for (i=0;ptr < endline -2;ptr++,i++) {
+ if (*ptr==' ' && *(ptr+1) == ' ') {
+ tmpmot[MIN(i, BUFFER_SIZE-1)] = '\0';
+
+ motarr = (char **)realloc( motarr, (motct+1) * sizeof(char *));
+ onemot = (char *) malloc (i+2);
+ strcpy(onemot,tmpmot);
+ motarr[motct] = onemot;
+
+ motct++;
+ i=-1;
+ for(;*(ptr+1) == ' ' && ptr < endline -1;ptr++);
+ } else if (i < BUFFER_SIZE) {
+ tmpmot[i] = *ptr;
+ }
+ }
+ if (*ptr != ' ') { tmpmot[i] = *ptr; i++; }
+ ptr++;
+ if (*ptr != ' ') { tmpmot[i] = *ptr; i++; }
+
+ tmpmot[i] = '\0';
+ motarr = (char **)realloc( motarr, (motct+1) * sizeof(char *));
+
+ onemot = (char *) malloc (i+2);
+ strcpy(onemot,tmpmot);
+ motarr[motct] = onemot;
+
+ motct++;
+
+ }
+
+ /*
+ * Save in specfile structure
+ */
+ sf->no_motor_names = motct;
+ sf->motor_names = (char **)malloc(sizeof(char *) * motct);
+ for (i=0;i<motct;i++) {
+ sf->motor_names[i] = (char *)strdup(motarr[i]);
+ }
+
+ *names = motarr;
+ return( motct );
+
+}
+
+
+DllExport char *
+SfMotor( SpecFile *sf, long index, long motnum, int *error )
+{
+
+ char **motors=NULL;
+ long nb_mot;
+ char *motor=NULL;
+ long selection;
+
+ /*
+ * go to scan
+ */
+ if (sfSetCurrent(sf,index,error) == -1) {
+ return((char *)NULL);
+ }
+
+ if ( sf->no_motor_names != -1 ) {
+ nb_mot = sf->no_motor_names;
+ } else {
+ nb_mot = SfAllMotors(sf,index,&motors,error);
+ }
+
+ if (nb_mot == 0 || nb_mot == -1) return((char *)NULL);
+
+ if ( motnum < 0 ) {
+ selection = nb_mot + motnum;
+ } else {
+ selection = motnum - 1;
+ }
+
+ if (selection < 0 || selection > nb_mot - 1 ) {
+ *error = SF_ERR_COL_NOT_FOUND;
+ if (motors != (char **) NULL)
+ freeArrNZ((void ***)&motors,nb_mot);
+ return((char *)NULL);
+ }
+
+ if (motors != (char **) NULL) {
+ motor = (char *)strdup(motors[selection]);
+ freeArrNZ((void ***)&motors,nb_mot);
+ } else {
+ motor = (char *)strdup(sf->motor_names[selection]);
+ }
+ return( motor );
+}
+
+
+DllExport long
+SfAllMotorPos ( SpecFile *sf, long index, double **retpos, int *error )
+{
+ char **lines;
+ char *thisline,
+ *endline;
+
+ double *posarr;
+
+ static double pos[300];
+ static char posstr[40];
+
+ char *ptr;
+
+ long motct = 0;
+ long no_lines;
+ short i,j;
+
+#ifndef _GNU_SOURCE
+#ifdef PYMCA_POSIX
+ char *currentLocaleBuffer;
+ char localeBuffer[21];
+#endif
+#endif
+
+ if (sfSetCurrent(sf,index,error) == -1) {
+ *retpos = (double *) NULL;
+ return(0);
+ }
+
+ /*
+ * if motors position for this scan have already been read
+ */
+ if (sf->motor_pos != (double *)NULL) {
+ posarr = (double *)malloc(sizeof(double) * sf->no_motor_pos);
+ for (i=0;i<sf->no_motor_pos;i++) {
+ posarr[i] = sf->motor_pos[i];
+ }
+ *retpos = posarr;
+ return(sf->no_motor_pos);
+ }
+
+ /*
+ * else
+ */
+ no_lines = SfHeader(sf, index,"P",&lines,error);
+
+ if (no_lines == -1 || no_lines == 0 ) {
+ *retpos = (double *) NULL;
+ return(-1);
+ }
+
+ motct = 0;
+#ifndef _GNU_SOURCE
+#ifdef PYMCA_POSIX
+ currentLocaleBuffer = setlocale(LC_NUMERIC, NULL);
+ strcpy(localeBuffer, currentLocaleBuffer);
+ setlocale(LC_NUMERIC, "C\0");
+#endif
+#endif
+ for (j=0;j<no_lines;j++) {
+ thisline = lines[j] + 4;
+ endline = thisline + strlen(thisline);
+ for(ptr=thisline;*ptr == ' ';ptr++);
+ for (i=0;ptr < endline -1;ptr++,i++) {
+ if (*ptr==' ') {
+ posstr[i] = '\0';
+
+ pos[motct] = PyMcaAtof(posstr);
+
+ motct++;
+ i=-1;
+ for(;*(ptr+1) == ' ' && ptr < endline -1;ptr++);
+ } else {
+ posstr[i] = *ptr;
+ }
+ }
+ if (*ptr != ' ') {
+ posstr[i] = *ptr;
+ i++;
+ }
+ posstr[i] = '\0';
+ pos[motct] = PyMcaAtof(posstr);
+
+ motct++;
+
+ }
+
+#ifndef _GNU_SOURCE
+#ifdef PYMCA_POSIX
+ setlocale(LC_NUMERIC, localeBuffer);
+#endif
+#endif
+
+ /*
+ * Save in specfile structure
+ */
+ sf->no_motor_pos = motct;
+ sf->motor_pos = (double *)malloc(sizeof(double) * motct);
+ memcpy(sf->motor_pos,pos,motct * sizeof(double));
+
+ /*
+ * and return
+ */
+ posarr = (double *) malloc ( sizeof(double) * motct ) ;
+ memcpy(posarr,pos,motct * sizeof(double));
+
+ *retpos = posarr;
+
+ return( motct );
+}
+
+
+DllExport double
+SfMotorPos( SpecFile *sf, long index, long motnum, int *error )
+{
+
+ double *motorpos=NULL;
+ long nb_mot;
+ double retpos;
+ long selection;
+
+ if (sfSetCurrent(sf,index,error) == -1)
+ return(HUGE_VAL);
+
+ if (sf->no_motor_pos != -1 ) {
+ nb_mot = sf->no_motor_pos;
+ } else {
+ nb_mot = SfAllMotorPos(sf,index,&motorpos,error);
+ }
+
+ if (nb_mot == 0 || nb_mot == -1) return(HUGE_VAL);
+
+ if ( motnum < 0 ) {
+ selection = nb_mot + motnum;
+ } else {
+ selection = motnum - 1;
+ }
+
+ if (selection < 0 || selection > nb_mot - 1 ) {
+ *error = SF_ERR_COL_NOT_FOUND;
+ if (motorpos != (double *)NULL)
+ free(motorpos);
+ return(HUGE_VAL);
+ }
+
+ if (motorpos != (double *)NULL) {
+ retpos = motorpos[selection];
+ free(motorpos);
+ } else {
+ retpos = sf->motor_pos[selection];
+ }
+ return( retpos );
+}
+
+
+DllExport double
+SfMotorPosByName( SpecFile *sf, long index, char *name, int *error )
+{
+ char **motors=NULL;
+
+ long nb_mot,
+ idx,
+ selection;
+ short tofree=0;
+
+ if (sfSetCurrent(sf,index,error) == -1)
+ return(HUGE_VAL);
+
+ if ( sf->no_motor_names != -1 ) {
+ nb_mot = sf->no_motor_names;
+ motors = sf->motor_names;
+ } else {
+ nb_mot = SfAllMotors(sf,index,&motors,error);
+ tofree=1;
+ }
+
+ if (nb_mot == 0 || nb_mot == -1) return(HUGE_VAL);
+
+ for (idx = 0;idx<nb_mot;idx++) {
+ if (!strcmp(name,motors[idx])) break;
+ }
+
+ if (idx == nb_mot) {
+ if (tofree) freeArrNZ((void ***)&motors,nb_mot);
+ *error = SF_ERR_MOTOR_NOT_FOUND;
+ return(HUGE_VAL);
+ }
+
+ selection = idx+1;
+
+ return(SfMotorPos(sf,index,selection,error));
+}