| Getting Started | Documentation | Glish | Learn More | Programming | Contact Us |
| Version 1.9 Build 1556 |
|
Creating a Useful Glish Client (C), Glen Langston, NRAO-GB
2003 April 22
A (gzipped) postscript version of this note is available (40kB).
This document describes the components needed to create a glish client. Two types of interfaces between C and glish are shown, 1) passing strings and 2) arbitrary sized double precision arrays.
The steps for construction, testing and execution are given.
In appendices, the glish and C++
code is listed.
To view the entire C code functions, down-load the
tar file from the web. This document and the code are on the web at:
http://www.gb.nrao.edu/
glangsto/aips++/glishClient
This document is an update of the examples created
by Rick Fisher in 1997.
Rick's document is useful as an
example of how any type of Glish variable can be passed
between glish, C, Fortran and C++.
See:
http://www.gb.nrao.edu/
rfisher
% ott 1408
Calculating flux densities for frequency 1408.000000 MHz
CASA 2092.0688+/- 160.548
3C286 14.6208+/- 0.940
3C48 16.3005+/- 1.192
3C147 22.0340+/- 1.384
3C138 8.4819+/- 0.848
1934-638 16.2053+/- 1.621
3C405 2706.6796+/- 429.630
DR21 26.6606+/- 3.627
NGC7027 7.9449+/- 3.972
3C295 22.2488+/- 1.676
3C123 47.3906+/- 4.739
3C161 18.6043+/- 1.860
3C218 42.7130+/- 4.271
3C227 7.6057+/- 0.380
3C249.1 2.2779+/- 0.228
VIRA 203.1464+/- 10.157
3C309.1 7.4350+/- 0.520
3C348 46.9291+/- 2.346
3C353 56.3030+/- 2.815
1.0000+/- 1.000
Epoch 2002DEC02 Cas-A Flux density based on 22.92 year decrease
Cas-A decrease factor: 0.9907/yr => 0.8081 total factor
CASA 1690.5828+/- 129.737
The ott program will also calculate the flux density for a single source at a single frequency. This capability is used in ottClient.g, function ottShell() to call a C program from glish.
% ott -s 3C286 1408 14.6208
% mkdir ottClient # create a new directory % cd ottClient # go to the directory % wget http://www.gb.nrao.edu/~glangsto/aips++/ott.tar #use wget or ftp % tar -xvf ott.tar # separate the components % emacs MakeOtt # edit the makefile for local paths % source /home/aips++/stable/aipsinit.sh # setup the aips environment % make # create the programs
The tar-ball ott.tar also contains the executables for RedHat Linux. The make step can be skipped if ott works properly at the command line prompt. The individual components of ott.tar are at: http://www.gb.nrao.edu/simglangsto/aips++/
Next, the shell environment variables must be configured for the local aips++ installation. This is done with a Unix script. Consult with your aips++ expert to find the script.
The client is tested during loading in the glish session. An example session is:
% bash # start the bash shell % source /home/aips++/stable/aipsinit.sh AIPS++ Version 1.8 Build 321 % glish -l ottClient.g reading .glishrc_local from /home/aips++/stable2 Test Execution of Ott functions: ottSourceName ( '3C295') := T freqs := [2e+08 3e+09 4e+10 5e+11] (Hz) ottFluxes( freqs) := [76.2198 11.0079 0.379414 0.00340961] (Jy) ottShell( '3C295', freqs) := [76.2198 11.0079 0.379414 0.00341] (Jy) Glish version 2.7. - exit
The function ottShell() works fine for a few flux density values. However its performance is too slow for an array larger than a thousand or so frequencies. In this case the function ottFluxes() is far superior.
% ott
ott: prints Ott et al 1994 and Baars et al 1977 flux densities.
usage: ott [-s <sourceName>] [-d <epoch>] frequencyMHz
where [-s <sourceName] is the optional source name.
where <frequencyMHz> frequency for model flux densities
where [<epoch>] optional date string for calculating Cas-A decay
string is in YYmmmDD format (ie 99feb04 or 05apr01)
The models of Ott, M. Witzel, A., Quirrenbach, A., Kirchbaum, T.P.
Standke, K., J., Schalinski, C. J., and Hummel, C.A.,
1994 Astronomy and Astrophysics, Vol 284 pg 331 and
Baars, Genzel, Pauliny-Toth and Witzel 1977, Astronomy and
Astrophysics, Vol 61, page 99 are used.
The Ott et al models are good for 1408 to 23000 MHz for most sources
For DR21, the Baars et al 1977 model is used.
For Cas-A, the current date is used to calculate flux density
Based on the Baars epoch 1980 model for decline in flux densities
Cas-A Model: 0.97+/.04 - 0.30+/-.04 log(freq./GHz) percent decrease/year
The Error estimates are approximate, using values in the text and
interpolating. The default is 5 percent.
Sources Modeled:
CASA 111-2 2323+588
3C286 1328+307 1331+305
3C48 0134+329 0137+331
3C147 0538+498 0542+498
3C138 0518+165 0521+166
1934-638
3C405 CYGA 1957+406
DR21 2037+421 2039+423
NGC7027 2105+420 2107+422
3C295 1409+524 1411+522
3C123 0433+295 0437+296
3C161 0624-058 0627-058
3C218 0915-119 0918-120
3C227 0945+077 0947+074
3C249.1 1100+772 1104+769
VIRA 1228+127 1230+123
3C309.1 1458+718 1459+716
3C348 1648+051 1651+049
3C353 1717-009 1720-009
#File ottClient.g, version 1.3, released 02/12/02 at 11:26:08
# retrieved by SCCS 02/12/02 at 11:26:18
#Glish event wrapper functions for calling C functions from Glish
#HISTORY
# 021202 GIL change ottFlux to ottShell
# 021122 GIL minor initial version based on ex_client.g
# 021115 GIL initial version based on ex_client.g
# 021114 GIL update for minor changes to glish
# 970803 JRF Initial version very well documented at
# http://www.gb.nrao.edu/~rfisher/Glish/ex_client.html
global ottSource := '3C286'
ottFluxes := function ( valu )
# ottFluxes takes an array of frequencies (Hz) and returns an array of
# flux densities (Jy). Must first set the source name with ottSourceName()
{
freqFluxes := as_double( valu) #/* transfer frequencies */
oFluxes := sf->ottSetFlux( freqFluxes);
return (oFluxes)
} #/* end of ottFluxes() */
ottSourceName := function ( sourceName )
{ #store source name as global with error checking
# INPUTS: sourceName string name of source "CASA" or "3C286" etc
global ottSource;
ottSource := as_string( sourceName);
global sf := client('ottClient');
dummyValue := sf->ottSetSource( ottSource); #/* now set the source name */
return(T)
} #/* end of ottSourceName() */
ottShell := function ( sourceName, frequencyVector)
{ # ottFlux gets a single ott et al flux via a commandline interface to ott.
# INPUTS: sourceName string name of source "CASA" or "3C286" etc
# frequencyVector Array of frequencies (Hz)
# OUTPUT: fluxVector Array of flux densities (Jy)
# This function is 100 times slower than ottFluxes()
frequencyShape := shape( frequencyVector);
if ( length( frequencyShape) > 1) {
print "Frequency vector must be one dimensional!"
return 0;
}
n := frequencyShape[1]; # get number of frequencies
fluxVector := array( 0, n); # create output array
frequencyMHz := as_double( frequencyVector) * 0.000001; #from Hz to MHz */
for (i in (1:n)) { # for all frequencies
shellString := sprintf( "ott -s %s %f", sourceName, frequencyMHz[i]);
# execute the shell string and convert to double
fluxVector[i] := as_double( shell( shellString));
} # end for all frequencies
return fluxVector;
} # end of ottShell
freqs := [ 2e8, 3e9, 4e10, 5e11]; # set the test frequencies
print ''
print 'Test Execution of Ott functions:'
print 'ottSourceName ( \'3C295\') :=', ottSourceName( '3C295');
print 'Freqs :=', freqs, "(Hz)";
print 'ottFluxes( freqs) :=', ottFluxes( freqs), "(Jy)";
print 'ottShell( \'3C295\', freqs) :=', ottShell( '3C295', freqs),"(Jy)";
/* File ottClient.cc, version 1.2, released 02/12/02 at 11:42:52
retrieved by SCCS 02/12/02 at 11:43:21
C++ client code wrapper for C functions to calculate the Ott et al fluxes.
HISTORY
021202 GIL remove un-used segments of the code.
021118 GIL add some comments
021115 GIL Initial version based on ex_client.cc
021114 GIL Removed support for complex functions
970803 JRF Initial version, well documented at
http://www.gb.nrao.edu/~rfisher/Glish/ex_client.html
DESCRIPTION
Rick Fisher created a very nice set of example code that allows an
observer to quickly create a interface from C to glish.
This function impliments the C++ wrapper to a simple C program to calculate
the Ott et al 1994 flux densities for a set of reference sources.
There are two steps in the process: First is setting the source name
for which the values are calculated. The second step is providing
an array of frequencies (Hz), for which the flux densities are required.
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Glish/Client.h"
// Declare all of the C/C++ functions that you are going to use or put
// the main() function at the end.
void setFluxes(Client &c, GlishEvent *e);
void setSource(Client &c, GlishEvent *e);
extern "C" {
char * setOttSourceName( char * source);
char * setOttSourceFluxes( long n, double values[]);
} /* end of C declares */
int main (int argc, char **argv) {
// This creates a required client object.
Client c(argc, argv);
// The client can be invoked with arguments, but we`ll bypass that
// complication.
if (argc > 1) { /* if any argument, explain usage */
printf ("Usage: cl := client('ex_client')\n");
return 1;
} /* end if an argument */
// Create a pointer to be assigned to a received glish event.
GlishEvent *e;
// Stay in this loop until the client is terminated. The c.NextEvent()
// function blocks until it receives an event from glish. It then
// returns an event pointer that is used to access the values passed
// from glish.
while ((e = c.NextEvent())) {
// Search for an expected event name and execute the appropriate
// function when found.
// vvvvvvvvvvvv Your code substituted below here. vvvvvvvvvvvv
if (!strcmp(e->Name(), "ottSetSource")) {
setSource( c, e);
} else if (!strcmp(e->Name(), "ottSetFlux")) {
setFluxes( c, e);
// ^^^^^^^^^^^^ Your code substituted above here. ^^^^^^^^^^^^
} else {
// Report an error if an event name is not recognized.
c.Unrecognized();
}
}
return 0;
} /* end of client main() */
void setFluxes(Client &c, GlishEvent *e)
{
// See do_int_squared() function for comments on statements which
// are common to all functions.
Value *val = e->Val();
long array_length = val->Length(), i = 0;
double *return_value = new double[array_length];
for (i = 0; i < array_length; i++) /* default value is 1. */
return_value[i] = 1.0;
if (val->Type() != TYPE_DOUBLE || array_length <= 1) {
printf("Double type array expected from `setFluxes'\n");
} else {
double * dataValues = val->DoublePtr();
double * freqFluxes = new double[array_length];
// vvvvvvvvvvvv Your code substituted below here. vvvvvvvvvvvv
for (i = 0; i < array_length; i++)
freqFluxes[i] = dataValues[i];
setOttSourceFluxes( array_length, freqFluxes);
for (i = 0; i < array_length; i++) /* transfer out */
return_value[i] = freqFluxes[i];
// ^^^^^^^^^^^^ Your code substituted above here. ^^^^^^^^^^^^
delete freqFluxes;
} /* end else if data of expected type */
Value *rep = new Value(return_value, array_length, COPY_ARRAY);
c.Reply(rep);
delete return_value;
Unref(rep);
} /* end of setFluxes() */
#define MAXSIZE 100 /* set string max size */
void setSource(Client &c, GlishEvent *e) {
// setSource() takes the source name event and transfers the name to the C
// functions.
Value *val = e->Val();
char return_value[MAXSIZE] = "", sourceName[MAXSIZE] = "", * errMsg = '\0';
if (val->Type() != TYPE_STRING) {
printf("String type value expected from `reverse_string'\n");
} else {
char *received_value = val->StringVal();
strncpy( sourceName, received_value, MAXSIZE);
sourceName[MAXSIZE-1] = '\0';
// The call of val->StringVal() implicitly allocates memory
// for the string which must be deleted to avoid a memory leak.
delete received_value;
// vvvvvvvvvvvv Your code substituted below here. vvvvvvvvvvvv
errMsg = setOttSourceName( sourceName);
if (errMsg != '\0') /* check for error strings */
strcpy( return_value, "!!!! ");
strcat( return_value, sourceName);
// ^^^^^^^^^^^^ Your code substituted above here. ^^^^^^^^^^^^
}
Value *rep = new Value(return_value);
c.Reply(rep);
Unref(rep);
} /* end of setSource() */
#Make file for C++ wrapper to C code for Ott et al 1994 flux densities. #HISTORY # 021122 GIL Add make file for stand alone program ott # 021118 GIL Update for configuration changes in GB. # 970101 JRF Initial version #DESCRIPTION #This make file creates two programs #ottClient: glish client allowing a glish session to call C functions #ott: stand alone program (linux or solaris) calc Ott etal # at the ATNF #BASE_DIR = /aips++ # at Green Bank #BASE_DIR = /aips++/test BASE_DIR = /home/aips++/stable #Now use Linux not solaris #LIBRARIES = -L$(BASE_DIR)/sun4sol_gnu/lib LIBRARIES = -L$(BASE_DIR)/linux/lib INCLUDES = -I$(BASE_DIR)/code/aips/glish/include -I./xlib #this make file makes two programs EXECUTABLES = ottClient ott all: $(EXECUTABLES) #selected code taken un-modified from the VLBA antenna control code and #OVLBI tracking station. VLBASTRINGS = str2mjd.o str2rad.o stripWhite.o time2str.o mjd2str.o \ srclist.o cvrtuc.o dateObs2DMjd.o today2mjd.o ottFluxes.o #the VLBA code environment includes definitions of C structures not #used here. This stub replaces the include with the standard definitions vlb.h : ln -s STDDEFS.H vlb.h #The VLBA code contains two great general purpose includes of constant values #Math constants and the definitions of TRUE, FALSE etc. $(VLBASTRINGS) : MATHCNST.H STDDEFS.H vlb.h $(@:.o=.c) #now describe how to compile CC=gcc CFLAGS= -O -Wall -g $(INCLUDES) $(LIBRARIES) COMPILE.c= $(CC) $(CFLAGS) $(CPPFLAGS) -c #rule for converting .c to a .o file .c.o : @ $(RM) $@ $(COMPILE.c) $< ottClient.o : ottClient.cc g++ $(INCLUDES) -c ottClient.cc ottClient : ottClient.o $(VLBASTRINGS) $(OTTCLIENTC) g++ -o ottClient $(OTTCLIENTC) $(VLBASTRINGS) ottClient.o \ $(LIBRARIES) -lglish -lsos -lnpd -lm ott : ott.o $(VLBASTRINGS) $(OTTCLIENTC) $(CC) $(CFLAGS) -o ott $(OTTCLIENTC) $(VLBASTRINGS) ott.o -lm