McIDAS Programmer's Manual

Chapter 4 - McIDAS-X Utilities

This chapter describes many of the McIDAS-X library functions that you will use when writing your applications programs. These utility functions perform a variety of common programming tasks, such as:

This chapter is organized into these sections

Overview

The McIDAS-X library functions presented in this chapter are the building blocks for your applications programs. These functions abstract the hardware, such as the display, keyboard and pointing device, and provide routines for manipulating scalar quantities, such as dates and latitudes.

When a user starts a McIDAS-X session, a display similar to the one shown in Figure 4-1 appears on the screen. The window in the foreground is the McIDAS-X Text and Command Window. The window in the background is the McIDAS-X Image Window.

Figure 4-1. At start-up, the McIDAS-X display contains the McIDAS-X Text and Command
Window and the McIDAS-X Image Window.

The visual output of your programs is displayed on these windows. Input is received from the keyboard via the command line and from the pointing device, or mouse, via the Image Window and cursor. Applications also make use of the terminal characteristics, the state of the McIDAS-X session and the application environment.

The functions described in this chapter are grouped by the tasks they perform:

User interface utilities

Users ultimately interact with McIDAS-X in one of two ways:

This section describes each part of the McIDAS-X command line, provides descriptions and examples of the command-line functions you can use in your programs, and defines the return status codes for these functions. This section also describes the standard pointing device for McIDAS-X and provides descriptions and examples of the functions available for reporting the state of the mouse buttons and changing the cursor's location, size, color and type.

 

For additional information about the functions described in this section, see the online man pages provided with the McIDAS-X software.

Command line

McIDAS-X applications are command-line driven. McIDAS-X has two basic command formats:

The multiple-letter command format is discussed in this section. The number of characters permitted in a command line is workstation dependent, although there is no practical limit.

A McIDAS-X command line may contain one or more of the following:

A sample McIDAS-X command line is shown below.

Each command line value is separated by one or more blank spaces. Surround an individual parameter requiring blank spaces with single quotes (' ') so it is treated as one parameter.

Each part of the McIDAS-X command line is discussed below, followed by a description of the functions for extracting individual values from the command line and interrogating the structure of the command line.

Command positional parameters

Command positional parameters provide input to a command and must be entered in the exact order specified. Use them in commands that have options which the user must always enter. One advantage of positional parameters is minimizing the number of keystrokes a user types. Be careful not to negate this advantage by using so many positional parameters that the user can't remember them all.

Keywords

Like command positional parameters, keywords are used for entering command input. Unlike command positional parameters, they are optional for most McIDAS-X commands and can be entered in any order as long as they follow command positional parameters and precede quoted text.

Keyword parameters are often used to clarify commands with many complicated options. Although keywords can occur in any order, their positional parameters must be entered in the order indicated. Since users don't always specify all keyword positional parameters in a command, be sure to assign them reasonable defaults.

In addition to the keywords that an application has built into it, McIDAS-X has six global keywords, which are common to all McIDAS-X commands:

You can retrieve the parameters for these global keywords in your applications, as long as you don't change their functionality.

 

For more information about the McIDAS-X global keywords, see the McIDAS User's Guide.

Quoted text

Quoted text input is most often used when strings entered by a user require blank spaces. Each application can contain only one quote string and it must be the last part of the command the user enters. Using quote fields in McIDAS-X commands is relatively easy from the McIDAS-X Text and Command Window; running McIDAS-X commands with quote strings from Unix shell prompts is more difficult. For this reason, the preferred method for entering strings with spaces in them from the command line is to use a positional or keyword parameter and surround the string with single quotes.

Functions for extracting values from a command line

The McIDAS-X library functions for extracting individual values from the command line are listed alphabetically in the table below. These functions have similar calling sequences.

C function

Fortran function

Description

Mccmddbl

mccmddbl

extracts a value as a double precision number

Mccmddhr

mccmddhr

extracts a time value as a double precision number in units of hours

Mccmddll

mccmddll

extracts a latitude or longitude value as a double precision number in units of degrees

Mccmdihr

mccmdihr

extracts a time value as an integer value in the hhmmss format

Mccmdill

mccmdill

extracts a latitude or longitude value as an integer value in the dddmmss format

Mccmdint

mccmdint

extracts a value as an integer

Mccmdiyd

mccmdiyd

extracts a day value as an integer value in the Julian day format ccyyddd

Mccmdquo

mccmdquo

extracts a character string value from the quote field

Mccmdstr

mccmdstr

extracts a character string value

You can use any of these functions, except Mccmdquo/mccmdquo , to extract information from any command or keyword positional parameter.

All of the functions in the table above, except Mccmdquo /mccmdquo , expect the following arguments:

These functions, except Mccmdstr /mccmdstr , also expect the following additional information:

All the functions above perform similar operations when retrieving data from the command line, including:

McIDAS-X uses a special syntax for identifying keyword names in these functions within an application. This syntax identifies a mandatory and an optional section, separated by a period. For example, if you use FRAME as a keyword in a command, it may be used in the above functions as FRA.ME to denote only the first three characters are mandatory. The table below shows some acceptable and unacceptable forms the user can enter.

Acceptable forms

Unacceptable forms

FRA=

FR=

FRAM=

FRAEM=

FRAMENUM=

 

Keyword names can be letters or numbers, as long as the name is unique; that is, you can't use COL.OR and COL.UMN in the same command.

Below is a description of each function for extracting values from a command line, along with examples.

Sample TEST command

The sample output in the examples below is based on the following user-entered command string for the program TEST. If you see the line goto 999 in the code fragments, it means: exit the command and return an error status.

 TEST LIST 4 END=X 4:30 STA=03-APR-1996 12:30 PAR=T TD HEAD=WI 'Dane County' "Home of the Black Wolf

Extracting a character string value

Use the mccmdstr function to extract a value from the command line as a character string. The code fragment below extracts the value from the first command positional parameter and puts it in the character string option .

character*12 default
character*12 option
default = ' '
ok = mccmdstr(' ', 1, default, option)
if (ok .lt. 0)then
  goto 999
endif

When the TEST command runs, the variable option will contain the string LIST . If the user enters the string ABCDEFGHIJKLMN, an error occurs because option doesn't have room to store this string. The mccmdstr function prints the error message below and returns an error status.

TEST: first positional argument is too big --> ABCDEFGHIJKLMN
TEST: Must be a character string of no more that 12 chars.

The code below extracts the value of the second keyword positional parameter for the keyword HEAD and puts it in the character string mnhead.

character*12 default
character*24 mnhead
default = ' '
ok = mccmdstr('HEA.D', 2, default, mnhead)
if (ok .lt. 0)then
  goto 999
endif

When the TEST command runs, the variable mnhead will contain the string Dane County. This string includes whitespace because the parameter is surrounded by single quotes on the command line. Note the mandatory and optional keyword components. This call will ignore a keyword named HEAP, while it will read a keyword named HEADER.

Extracting an integer value

Use the mccmdint function to extract a value from the command line as an integer value. The following code fragment extracts the value of the second positional parameter as an integer. The call to mccmdint also performs range checking to verify that the value entered by the user is within the range 1 to 9999. If the user doesn't enter a value for the second positional parameter, the default value of 1 is used.

parameter (MINFILE = 1, MAXFILE = 9999)
integer fileno
ok = mccmdint(' ', 2, 'File Number', 1, MINFILE, MAXFILE, fileno)
if (ok .lt. 0)then
  goto 999
endif

When the TEST command runs, the variable fileno will contain the value 4. If the user enters the value 10000 for the second positional parameter, the range allowed in this mccmdint call is exceeded. Thus, mccmdint prints the following error message and returns an error status.

TEST: Invalid File Number.
TEST: 2nd positional argument is too big --> 10000
TEST: Must be valid 'File Number' integer value within range 1 thru 9999.

Extracting time information

The functions to extract time information, mccmddhr and mccmdihr , accept input in a variety of formats. To get a list of the acceptable formats, type the command ARGHELP TIME from the McIDAS-X Text and Command Window.

The following code fragment extracts the value of the second keyword positional parameter as an integer for the keyword START. Note that the call to mccmdihr also performs range checking to verify that the value entered by the user falls within the range 0 to 23:59:59. This is not done automatically, so you can also use these functions to extract an interval of time such as -18:45.

integer starttime
ok = mccmdihr('STA.RT', 2, 'Starting Time', 120000, 0, 235959, starttime)
if (ok .lt. 0)then
  goto 999
endif

When the TEST command runs, the variable starttime contains the value 123000. If the user doesn't enter a value for the second keyword positional parameter for the START keyword, the value returned in starttime is the default of 120000.

Be careful when setting ranges and default values for the mccmdihr function and using the returned values. The format expected is hhmmss . To specify 15:00:00 as the default for a command, you must enter 150000 as the fourth parameter in mccmdihr . If you specify 15 for the default, the value returned will be 00:00:15.

The following code fragment extracts the value of the second keyword positional parameter as a double precision number for the keyword END. The default value is five hours. Note that range checking is turned off in this example by setting the minimum value, 99.0, greater than the maximum value, -99.0.

double precision endtime
ok = mccmddhr('END', 2, 'Ending Time', 5.0d0, 99.0d0, -99.0d0, endtime)
if (ok .lt. 0)then
  goto 999
endif

When the TEST command runs, the variable endtime will contain the value 4.5.

Extracting date information

The function to extract date information, mccmdiyd , accepts input in a variety of formats. To get a list of the acceptable formats, type the command ARGHELP DATE from the McIDAS-X Text and Command Window.

The following code fragment extracts the value of the first keyword positional parameter for the keyword START. This call sets the default to the current day and does not perform range checking.

integer currentday
integer startday
ok = mcgetday(currentday)

ok = mccmdiyd('STA.RT', 1, 'Starting Day', currentday, 99, -99, startday)
if (ok .lt. 0)then
  goto 999
endif

When the TEST command runs, the variable startday will contain the value 1996094.

Extracting a character string value from a quote field

Use the mccmdquo function sparingly when extracting a quote string that contains whitespace. The preferred method for retrieving parameters containing whitespace is to use the mccmdstr function and have the user enter the parameter with single quotes (') as shown in the mccmdstr section above.

The following code fragment extracts the value of the quote string.

character*256 quote
ok = mccmdquo(quote)
if (ok .lt. 0)then
  goto 999
endif

When the TEST command runs, the variable quote will contain the string Home of the Black Wolf . If this field is missing from the user command, the variable is set to blank characters.

Functions for interrogating the command line structure

Sometimes applications need to get information from the command line beyond the actual values entered by the user. The functions described in the table below provide these services.

C function

Fortran function

Description

Mccmd

mccmd

returns the entire user command in one string

Mccmdkey

mccmdkey

verifies that the keywords entered by the user are valid

Mccmdnam

mccmdnam

returns a list of the keywords entered by the user

Mccmdnum

mccmdnum

returns the number of parameters entered for a particular keyword

Each function is described below, along with an example. The sample output is based on the user-entered command string for the program TEST, as shown in the section titled Sample TEST command above.

Verifying the validity of a keyword

Because of the complexity of the McIDAS-X command line, users will sometimes enter an incorrect keyword that is ignored and then not be able to determine why their command doesn't run properly. The mccmdkey function will verify that the keywords entered by the user are valid for the command. It compares the keywords the user enters with a list of acceptable keywords for a command and prints an error message if a discrepancy occurs. Additionally, mccmdkey checks your application to verify that it contains no ambiguous keywords; for example, COL.OR and COL.UMN.

The global keywords described earlier in this section are implicitly included in mccmdkey , so you don't need to include them in your list of keywords to be tested. Your cannot use the mccmdkey function if the keyword names in your command are not fixed; for example, cases where keyword names are related to data structures. Your program cannot predetermine the names the user may have entered; therefore, it cannot use mccmdkey .

The code fragment below shows how to validate the sample TEST command for the keywords END, FILE, PARAMETER, START and TITLE.

parameter (MAXKW = 5)
character*12 validkw(MAXKW)
data validkw/'END','FIL.E','PAR.AMETER','STA.RT','TIT.LE'/

ok = mccmdkey(MAXKW, validkw)
if (ok .lt. 0)then
  goto 999
endif

If the user enters the additional keyword argument COUNTRY=UK , the TEST command will output the following line to the McIDAS-X Text and Command Window and exit.

TEST: Invalid command keywords: COUNTRY=UK

Note that it is the programmer's responsibility to keep the keyword list used in mccmdkey consistent with the keywords actually used by the application. This checking can be turned off by the user by setting syskey word 15 to a non-zero value.

Retrieving a list of user-entered keywords

Sometimes an application needs to know exactly which keywords the user entered. The mccmdnam function will return this information. The code fragment below shows how to retrieve the list of user-entered keywords.

parameter (MAXKW = 5)
character*12 entered_kw(MAXKW)

n_ent = mccmdnam (MAXKW, entered_kw)
if (n_ent .lt. 0)then
  goto 999
endif

When the TEST command runs, the variables in this code fragment will contain the following values:


n_ent           = 4
entered_kw(1)       = 'END'
entered_kw(2)       = 'STA'
entered_kw(3)       = 'PAR'
entered_kw(4)       = 'TITLE'

Note that mccmdkey returns abbreviated values for the START and PARAMETERS keywords, since that is how they were entered on the command line.

Verifying the number of keyword parameters

When applications allow for multiple keyword positional parameters, you must be able to tell how many parameters the user actually included in the command. The mccmdnum function returns this information. The following code fragment extracts the number of keyword positional parameters that the user entered for the PARAMETER keyword.

integer n_parms

n_parms = mccmdnum('PAR.AMETER')

When the sample TEST command runs, n_parms will contain the value 2.

To find out how many command positional parameters the user entered, the code fragment would look like this:

n_parms = mccmdnum(' ')

Status codes

The command-line functions all return status codes. A non-negative value indicates a successful return. A value greater than zero indicates a successful return, but with additional information such as the parameter returned is the default value. A value less than zero indicates a problem, for example in the formatting or range checking. The argument fetching status codes are defined in the table below.

The status codes use the format abcd. The value in the a position indicates the parameter's location; for example, the command line or string table. The values in the b and c positions indicate the form of the value; for example, time or angle. The value in the d position indicates the status.

Status code

Definition

[-]0bcd

argument comes from the default

[-]1bcd

argument comes from the command line

[-]2bcd

argument comes from the McIDAS-X string table

[-]a00d

character string argument

[-]a01d

quote field string argument

[-]a10d

integer argument

[-]a11d

integer hexadecimal argument

[-]a20d

double decimal argument

[-]a21d

double hexadecimal argument

[-]a30d

date argument

[-]a31d

current date argument

- a32d

year within date argument is invalid

- a33d

mon month within date argument is invalid

- a34d

mm month within date argument is invalid

- a35d

day of month (dd) within date argument is invalid

- a36d

day of year (ddd) within date argument is invalid

[-]a40d

integer time argument

[-]a41d

current integer time argument

- a42d

hours within integer time argument are invalid

- a43d

minutes within integer time argument are invalid

- a44d

seconds within integer time argument are invalid

[-]a45d

double time argument

[-]a46d

current double time argument

- a47d

hours within double time argument are invalid

- a48d

minutes within double time argument are invalid

- a49d

seconds within double time argument are invalid

[-]a50d

integer lat/lon argument

- a52d

degrees within integer lat/lon argument are invalid

- a53d

minutes within integer lat/lon argument are invalid

- a54d

seconds within integer lat/lon argument are invalid

[-] a55d

double lat/lon argument

- a57d

degrees within double lat/lon argument are invalid

- a58d

minutes within double lat/lon argument are invalid

- a59d

seconds within double lat/lon argument are invalid

[-] 90d

keyword status

abc0

argument is ok

- abc1

argument has an invalid character

- abc2

integer argument can't contain a fraction

- abc3

argument exceeds system limits for desired format

- abc4

out-of-range argument < given min

- abc5

out-of-range argument > given max

Pointing device

The standard pointing device is usually a three-button mouse. The leftmost button is used by the window manager and the middle and right buttons are used by the McIDAS-X mouse interface.

If you have a two-button mouse, the left button is used by the window manager and the right button performs the tasks normally performed by the right button on a three-button mouse. Press both buttons to perform the tasks normally performed by the middle mouse button. Check the mouse settings in our X-server configuration if you see unexpected behavior.

Users can interact with the McIDAS-X Image Window and McIDAS-X commands via the mouse-driven cursor. McIDAS-X defines the cursor's size, color and shape as long as the cursor resides on the McIDAS-X Image Window. If the cursor is moved outside the window, the cursor's size, color and shape revert to the workstation's settings.

The McIDAS-X function for interfacing with the mouse is mcmoubtn , which performs the following tasks:

You can use the McIDAS-X functions putcur , mcgetcur , sizcur , colcur and typcur in your applications to define the cursor's location, size, color and type. The function mcgetcur will return the cursor position of the cursor when your command starts.

Reporting the state of the mouse buttons

The mcmoubtn function reports the state of the mouse buttons as soon as a mouse button event occurs. Button events include the following:

Applications specify which of the above events triggers a response via the first argument of the mcmoubtn function. Once the event occurs, the state of each mouse button and the cursor's line and element position in the McIDAS-X Image Window are returned to the calling application.

Calling mcmoubtn inherently causes the application to sleep or idle. Thus, you can call it within tight, intensive loops without fear of saturating the processor. If, at any time, the desired mouse event does not occur within a two-minute time span, mcmoubtn returns a timeout status to the calling application. The application is free to call mcmoubtn again if that two-minute time span is not considered unusual.

The code fragment below, from the McIDAS-X ZLM command, monitors the mouse event status.

     parameter button_release=3
     ....
     
c---wait for mouse release
10  status=mcmoubtn(button_release,button(1),button(2),tvlin,tvele)

c---end mouse button sampling
   if((button(1).ne.0.and.button(2).ne.0).or.status.ne.0) then
       call beep(50,10)
       goto 100

c---on left mouse button press

   else if(button(1).ne.0) then

   ......

Note that the mcmoubtn function neither tests for nor protects against two applications using it at the same time. If several applications that call mcmoubtn are started concurrently, the results may be unpredictable.

Reporting the status of Alt G and Alt Q

The mcmoubtn function also indicates the status of the keyboard toggles Alt G and Alt Q, which are monitored by McIDAS-X similar to the mouse buttons. If you hold down the Alt key on the keyboard and press either the G or Q key, mcmoubtn will report that Alt G or Alt Q was pressed. These keyboard toggles are useful when you need to precisely position the cursor on the McIDAS-X Image Window and the act of clicking a mouse button may cause the mouse to move.

Defining cursor location, size, color and type

Use the functions below to change the appearance of the McIDAS-X cursor.

Fortran function

Description

putcur

moves the cursor to a specified location

sizcur

changes the cursor size

colcur

changes the cursor color

typcur

changes the cursor type; for example, crosshair or box

The values that these functions place into User Common are used by the mcimage program to define the appearance of the McIDAS-X cursor. The example below illustrates the use of these cursor functions.

    integer line, element
    integer height, width
    integer color
    integer type

    ..
C Define the new location of the cursor
    line = 200
    element = 351

C Define the new height and width; note: these values must be ODD
    height = 23
    width = 13

C Reassign the cursor to be displayed in color level 3
    color = 3

C Define the new type; 1=box, 2=cross-hair, 3=both, 4=solid,
C 5=bullseye
    type = 3

C Now make the change:

    call putcur ( line, element )
    call sizcur ( height, width )
    call colcur ( color )
    call typcur ( type )

...

Display utilities

The McIDAS-X library provides many functions for displaying text on the McIDAS-X Text and Command Window and displaying images and graphics on the McIDAS-X Image Window.

This section provides descriptions and examples of the functions that you can use in your programs to display text, images and graphics on the McIDAS-X windows, and to obtain information about the McIDAS-X display.

 

For additional information about the functions described in this section, see the online man pages provided with the McIDAS-X software.

Text messages

McIDAS-X has three types of text messages that you can use in your applications:

You should insert debug messages to help trace progress in applications, avoiding extraneous or misleading messages. Also avoid placing debug messages in code where thousands of lines of output could be generated. You will probably not have sufficient room on the McIDAS-X Text and Command Window to view that much output and even if the debug messages are suppressed, they will increase CPU usage unnecessarily.

Figure 4-2. The McIDAS-X Text and Command Window displays standard, error and debug text messages

Routing text

Text can be sent, or routed, to several destinations, as shown in the table below. Users enter the McIDAS-X global keyword, DEV, to specify the destination device of the text output generated by a command.

This DEV= option

Sends the output to

DEV=C

McIDAS-X Text and Command Window (default for standard and error messages)

DEV=P

printer

DEV=F

disk file; 80 characters per line

DEV=N

all output is discarded (default for debug messages)

DEV=T

text file

The user enters the disposition of the text messages as a series of three, contiguous disposition types in this order: standard, error, debug . For example, if the user enters DEV=CCC, all standard, error and debug messages are written on the McIDAS-X Text and Command Window. Entering DEV=CNN displays only the standard messages on the window; the error and debug messages are suppressed. The default is DEV=CCN, meaning the standard and error messages are written on the McIDAS-X Text and Command Window and the debug messages are suppressed.

 

For more information about McIDAS-X global keywords, see the McIDAS User's Guide.

Generating text

To display standard, error and debug messages in C or Fortran applications, use the library functions shown in the table below.

C function

Fortran function

Message type

Mcprintf

sdest

standard text

Mceprintf

edest

error

Mcdprintf

ddest

debug

The sample code below illustrates the use of each message type in a Fortran application.

      subroutine main0
C $ ABCD - illustrates message disposition

      implicit none

c --- external functions
      integer mccmdint   ! integer arg fetch

c --- internal variables
      integer parameter  ! 1st parameter

c --- get the first positional parameter from the command line
      if( mccmdint(' ',1,'1st Parameter',1,1,0,parameter).lt.0)
    & return

      call sdest('STANDARD -- First parameter =',parameter)
      call edest('ERROR -- First parameter =',parameter)
      call ddest('DEBUG -- First parameter =',parameter)

      return
      end

The following table shows where text would be routed, based on the application, ABCD, presented in the code above.

Entering this command

Results in

Output goes to

ABCD 100

STANDARD -- First parameter =100
ABCD: ERROR -- First parameter =100

both messages go to the McIDAS-X Text and Command Window

ABCD 200 DEV=CCC

STANDARD -- First parameter =200
ABCD: ERROR -- First parameter =200
ABCD*DEBUG -- First parameter =200

all messages go to the McIDAS-X Text and Command Window

ABCD 300 DEV=PPF YY

STANDARD -- First parameter =300
ABCD: ERROR -- First parameter =300
ABCD*DEBUG -- First parameter =300

printer
printer
disk file named YY

ABCD 400 DEV=NNN

 

no output

If you don't have an integer value to be printed at the end of sdest, edest or ddest calls, specify zero as the second argument. These functions don't print an integer value of zero. To print a zero, format it into the string. The lines below show the use of a Fortran write to format a text message.

   write(cline,fmt='(a18,1x,f9.2)')'the temperature is',temp
   call sdest(cline,0)

You can create the same formatted output with the following C call.

(void) Mcprintf ("the temperature is %9.2f\n ",temp);

Although sdest, edest and ddest automatically insert a new line when they are called, you must explicitly include the new line character, \n, in applications calling Mcprintf, Mceprintf and Mcdprintf.

Images

An image is information that is usually represented as shades of gray in a two-dimensional matrix, such as a satellite image, a radar image or an image derived from grids. Images are displayed on the McIDAS-X Image Window, as shown in Figure 4-3.

Figure 4-3. The McIDAS-X Image Window displays McIDAS-X-generated images .

You will use the mcline function to write a line of image data into a frame object for display on the McIDAS-X Image Window. A frame object is a memory-based collection of information that completely describes the contents and appearance of a frame to the mcimage process, which creates a visible picture. A frame object contains the actual image data, along with navigation and color enhancement information. Frame objects are stored in McIDAS-X shared memory. The number and size of the frame objects allowed per McIDAS-X session are user-configurable.

The sample code below illustrates how to use mcline to write a frame object. Note that the mcline function writes an entire line. Use mclineseg to write only a partial line.

      integer array(1000)
      .
      .
      .
C --- get the image frame number
      frame = luc(51)

C --- get the size of the frame
      status = mcfsize(frame, num_lines, num_elems)
      if( status.lt.0 ) then
         call edest('Invalid image frame number=',frame)
         return
      endif

C --- fill the output array with a bounded gray scale
      do 10 elem = 1,num_elems
10    array(elem) = MOD( elem-1, 255 )

C --- write array to the frame object
      do 100 line = 1,num_lines
100   call mcline( frame, line, array )

The output from this code displays a series of black-to-white gray shades. It may not map to the McIDAS-X Image Window quite as you expect, however. McIDAS-X applications envision the McIDAS-X Image Window as being n lines by m elements, and capable of displaying 256 colors. Each element in the array holds a 1-byte value (0 to 255) representing a brightness value.

McIDAS-X applications use the mcline function to write image data, or brightness levels, into a frame object. The mcimage program then takes this 8-bit image data and maps it into the McIDAS-X Image Window. Because hardware configurations impose limitations on the number of displayable brightness levels, the image data in the frame object must pass through a filter that maps the brightness levels into the range of display levels. Consequently, the image brightness levels in the frame object rarely correspond one-to-one with the display levels in the McIDAS-X Image Window.

 

For more information about McIDAS-X image display characteristics, see the McIDAS-X TERM command with the SCALE option in the McIDAS User's Guide. Also see the section titled Displaying Images and Graphics in the Introduction chapter of the McIDAS User's Guide.

For more information about McIDAS-X shared memory and frame objects, see the section titled Shared memory in Chapter 2, Learning the Basics.

Graphics

McIDAS-X graphics appear to the user as text, symbols and line segments drawn in color on the McIDAS-X Image Window. Though displayed as part of the same frame object as images, graphics are manipulated through a separate, vector-based API. Vector-based means that graphics are produced by an imaginary drawing pen that can be moved about on the frame by function calls. The pen traces a line segment of the specified color as it moves, and the graphics subsystem converts this into the appropriate pixels and places it in the frame object. McIDAS-X also provides a simple interface for writing text and numbers as vector graphics.

This section describes how to use the graphics subsystem, providing both basic and advanced McIDAS-X graphics techniques. An extended example, GRAF.PGM, and the output it produces, accompanies much of the discussion. The listing for GRAF.PGM appears later in this section.

The table below alphabetically lists the McIDAS-X graphics functions used on the following pages. Additional graphics functions for displaying wind barbs, wind vectors, and weather symbols on a frame are provided later in this section.

Fortran function

Description

dshoff

turns the dash mode off

dshon

turns the dash mode on

endplt

closes or binds off the graphics frame

enpt

flushes the graphics buffer

initpl

initializes the graphics package to write to a frame object

newplt

erases the current graphics frame

page

resizes the viewport or world

plot

draws a line

pltdig

writes an integer number

qgdash

returns the current dash mode

qscale

returns the current scaling mode

sclhgt

converts text height from world to frame coordinates; use only if scaling is turned on; does not reduce the height of the text

scloff

turns scaling off; subsequent graphics calls use frame coordinates

sclon

turns scaling on; subsequent graphics calls use world coordinates

sclpnt

converts a point from world to frame coordinates

wrtext

writes a text string

Basic McIDAS-X graphics techniques

This section describes the techniques that you will most often use when working with the McIDAS-X graphics subsystem. Figure 4-4 below shows
a graphic produced by the sample GRAF application when run from a McIDAS-X session with no arguments and a frame size of 480 lines by
640 elements.

Figure 4-4. This GRAF.PGM output is the result of a McIDAS-X session run with
no arguments and a frame size of 480 lines by 640 elements.

To produce such a graphic, an application must do the following:

These procedures are described below.

Initializing the graphics subsystem

Before you can use the McIDAS-X graphics subsystem, you must initialize it with a call to initpl as shown in the following code fragment from GRAF.PGM, lines 88 to 93; frame is the number of the frame where the graphics will appear and width is the line width, in pixels. Specify zero to use the current frame and width.

C     // Initialize the plot and fetch the color

      frame = luc(-1)
      call initpl( frame, width )

      if( mccmdint('COL.OR', 1, 'Graphic Color', 3, 1, 3,
     &  color ) .lt. 0 ) return

Drawing lines

All graphics objects are composed of line segments built using the plot function. The graphics subsystem lets you specify the following line segment attributes:

Line color

The diagonal line in Figure 4-4 is generated by these lines of code (91 to 132) in GRAF.PGM:

      call initpl( frame, width )
      ...
      call plot( w_ullin, w_ulele, PEN_UP ) 
      call plot( w_lrlin, w_lrele, color  ) 
      call enpt

The second plot call draws the line in color level color from the previous cursor position to line w_lrlin and element w_lrele , here the lower-right corner of the frame. The previous position is always the one specified by the most recent plot call; the PEN_UP defined constant, with a value of zero, moves the pen from its previous, undefined location to the start of the line at (w_ullin,w_ulele ) without drawing.

To use a particular graphics form repeatedly, you can write a routine to generate it at the desired location with desired attributes. A simple example from GRAF.PGM, lines 263 to 286, is shown below.

      subroutine box( ullin, ulele, lrlin, lrele, color )

      <...variable declaractions deleted...>

      call plot( ullin, ulele, PEN_UP )
      call plot( ullin, lrele, color  )
      call plot( lrlin, lrele, color  )
      call plot( lrlin, ulele, color  )
      call plot( ullin, ulele, color  ) 
      call enpt
      ...

This example draws rectangles on the display with a single call and makes applications easier to write and understand.

Dash mode

The dash mode is set by the dshon and dshoff functions. To determine the current mode at any time, call the qgdash function.

When a McIDAS-X session starts, the dash pattern is preset to 10 pixels on and 10 pixels off. You can change this pattern using the McIDAS-X GD command, either from the command line before running any graphics applications, or within an application using the keyin or Mckeyin functions. These values are stored in User Common words 47 to 49.

Lines 146 to 151 in GRAF.PGM draw a dashed box to outline the viewport, which is described later, using the calls below.

      if( border .gt. 0 ) then
          call qgdash( old_dash )
         call dshon 
          call box( v_ullin, v_ulele, v_lrlin, v_lrele, color )
          if( old_dash .eq. 0 ) call dshoff 
      end if

Though not strictly necessary in this context, this sequence also illustrates a helpful idiom: capturing an aspect of graphics status (here the dashing state old_dash ), changing it to a known state (dshon) and then restoring the original state when done. Such behavior is especially important when writing library functions, since they should be careful to leave things the way they found them.

Line width

The line width is established when the graphics subsystem is initialized with initpl . To change the line width, you must close the current graphic and restart another, specifying a new width. Previously drawn graphics remain on the frame with the former line width and new graphics are drawn with the new line width.

Displaying text and numbers

The McIDAS-X library provides two graphics functions, wrtext and pltdig , for writing text and numbers on a graphics frame. When using these functions, you must designate the following:

Lines 361 to 386 in GRAF.PGM use wrtext to produce the alphanumeric characters shown in Figure 4-4 through its own plttext subroutine, as shown below.

C --- Determine the center point in frame coordinates. Because
C --- sclpnt() always works whether the world is active or not,
C --- make this call only if scaling is actually on.

      call qscale( sclstat )
      if( sclstat .eq. 1 ) then
         call sclpnt( clin, cele, txtclin, txtcele )
      else
          txtclin = clin
          txtcele = cele
      end if
C --- Determine the length of the text message in characters.
C --- This information is then used, together with the actual
C --- heights, to compute the upper left corner in frame coordinates
      nchar = len_trim( text )
      ullin = txtclin - txthgt/2
      ulele = txtcele - txthgt*nchar/2 + txthgt/10

C --- Display the text. Turn scaling off first (we have figured
C --- the text height and location in frame coordinates ourselves,
C --- right?) but be sure to restore it to its original state
C --- according to the result 'sclstat' of the qscale() call above
      call scloff
      call wrtext( ullin, ulele, txthgt, text, nchar, color )
      if( sclstat .eq. 1 ) call sclon

For titles and labels, it is often easier to decide where text should be centered rather than where its left margin should be. The above code uses the number of characters nchar and height in pixels txthgt to compute the offsets in line and element from the center to the upper-left. The internal plttext subroutine encapsulates the logic and other computations to account for graphics scaling so GRAF.PGM generates a centered line of text with a single call, just as box draws a graphics object in a clear, abstract way.

The pltdig function is similar to wrtext except that it also allows the user to specify the number of spaces. If the value to be plotted contains fewer digits, the result is left-padded with zeros.

Flushing the buffers

Because the graphics subsystem is buffered, graphics may not appear as they are being drawn. Interactive applications may need to force graphics to appear at various stages in the process. To do this, you must enter the call below to flush the buffers without ending the application's ability to draw additional graphics.

      call enpt

In the listing for GRAF.PGM, this is done at the end of the box and plttext subroutines (lines 286 and 388). All graphics drawn to that point become visible and the graphics package, including all graphics options the application may have set, remains active.

Binding off graphics

When you're done creating graphics, call the endplt function (line 224 in GRAF.PGM) to bind off the graphics as shown below.

      call endplt

Calling endplt displays all graphics on the McIDAS-X Image Window and frees all associated resources. To create more graphics on this or other frames, you will have to call initpl again.

Advanced McIDAS-X graphics techniques

This section describes some advanced techniques that you can use with the McIDAS-X graphics subsystem. It builds upon the example and the McIDAS-X session started in the previous section, Basic McIDAS-X graphics techniques.

Using world coordinates

The example presented in the previous section positioned and drew all graphics in terms of pixel locations on the screen, assuming the typical frame size of 480 lines by 640 elements. However, McIDAS-X frames don't have a fixed size. If you restart the previous McIDAS-X session with a frame size of 350 by 480 and rerun GRAF.PGM, the display will look like Figure 4-5 below.

Figure 5-5. This GRAF.PGM output is the result of a McIDAS-X session run with no arguments and a frame size of 350 lines by 480 elements.

Although the text is still centered on (240,320), this is no longer the center of the frame. The text message describing the frame size gets its values from this line of code (line 195) in GRAF.PGM:

      call mcfsize( frame, f_nlins, f_neles )

The upper-left corner is always (1,1) and the lower-right corner (f_lrlin, f_lrele ) can be readily computed from the size.

The problem of positioning graphics in frames of various sizes remains, however. An obvious solution is for the application to create its graphics objects in some normal coordinate system in which the frame always occupies the same range, whatever its physical size in pixels. McIDAS-X refers to such systems as scaled or world coordinates because they let graphics applications run in their own little world, which is always the size that the application finds convenient. McIDAS-X supports the use of world coordinates with the page, sclon, scloff, sclpnt and sclhgt functions.

To use world coordinates properly, you must understand the concepts of defining and activating worlds. The sclon function activates world coordinates (scaling) and scloff deactivates them. You can use only one coordinate system, either world or frame, at a time. All functions that generate graphics using a line or element pixel coordinate (plot, pltdig, wrtext) use the current system, whether frame or world. Frame coordinates are determined entirely by the hardware and/or the McIDAS-X session; world coordinates, on the other hand, may be defined to be convenient for the application. The initpl function defines a default world of 480 lines by 640 pixels; this world may be redefined using the page function. Keep in mind that page also activates the world it defines, whereas initpl does not.

In Figure 4-5, the world is defined to be 480 by 640 by initpl but not activated, as noted on the display. If you instead enter this command:

GRAF WORLD=1 1 480 640

GRAF.PGM looks at the four WORLD parameters and defines and activates a world using the code below (lines 99 to 117).

C   // If the user has specified the necessary four arguments to
C   // WORLD= read them and define the world; page()
C   // automatically activates it.
C   // The defaults are 1 1 480 640 but there is no significance
C   // to this here; the argfetchers will trigger a return
C   // if the user doesn't actually enter a legal value for
C   // each of the four positions

    if( mccmdnum('WORLD') .eq. 4 ) then
        if( mccmdint('WORLD',1, 'World upper left line',
   &      1, 1, 0, w_ullin ) .lt. 1100 ) return

    ...three more argfetches deleted...
    
    call page( w_ullin, w_ulele, w_lrlin, w_lrele, SET_WORLD )
    end if

The resulting output is shown in Figure 4-6 below.

Figure 4-6. This GRAF.PGM output uses world coordinates to position the text.

The diagonal now goes from corner to corner as in Figure 4-4 and the text is again centered even though the frame sizes are different. Making applications that can generate attractive, properly positioned output regardless of the physical size of the frame is the primary use of world coordinates and the page function. If a 480 by 640 world is suitable, you can just enter the calls below to activate initpl 's default world.

      call initpl( frame, width )
      call sclon

In general, you should use a world that is as large as or larger than your largest frame size to minimize truncation errors resulting from a single world pixel occupying multiple pixels of the frame.

One complication of world coordinates is the positioning and sizing of text. The wrtext function can be given positions and a height in either frame or world coordinates. If the world is smaller than the frame, the text is enlarged; if the world is larger than the frame, the text is not reduced. This prevents the text from becoming too small to read. The difficulty is that the application must be able to account for both cases when centering text. One solution is to do the positioning and output directly in frame coordinates even if scaling is on; the sclpnt and sclhgt functions allow explicit conversion of points and text heights from world to frame coordinates. The plttext subroutine in GRAF.PGM, lines 354 to 386, illustrates this technique as shown in the code samples below.

The actual text size in frame coordinates is determined first:

C --- Determine the actual (frame coordinates) height of the
C --- text. (The use of local variable 'txthgt' is needed to keep
C --- plttext() from modifying its inputs.)

      txthgt = hgt
      call sclhgt( txthgt )

The center point is then transformed to frame coordinates:

C --- Determine the center point in frame coordinates. Because
C --- sclpnt() always works whether the world is active or not,
C --- make this call only if scaling is actually on.
      call qscale( sclstat )
      if( sclstat .eq. 1 ) then
          call sclpnt( clin, cele, txtclin, txtcele ) 
      else
          txtclin = clin
          txtcele = cele
      end if

Then the upper-left corner is computed, again in frame coordinates:

C --- Determine the length of the text message in characters.
C --- This information is then used, together with the actual
C --- heights, to compute the upper-left corner in frame
C --- coordinates.
      nchar = len_trim( text )
      ullin = txtclin - txthgt/2
      ulele = txtcele - txthgt*nchar/2 + txthgt/10

Given that the position is in frame coordinates already, you must verify that scaling is off before calling wrtext and then be sure to restore the scaling to its original setting, whether off or on, before returning control to the caller:

C --- Display the text. Turn scaling off first (we have figured
C --- the text height and location in frame coordinates
C --- ourselves, right?) but be sure to restore it to its
C --- original state according to the result 'sclstat' of the
C --- qscale() call above.
      call scloff 
      call wrtext( ullin, ulele, txthgt, text, nchar, color )
      if( sclstat .eq. 1 ) call sclon

In the above examples, you used world coordinates to make graphics applications independent of frame size. You can also change the orientation and origin of world coordinates as well as their extent.

Some graphics such as scatter plots are easier to generate in an (x,y ) coordinate system in which x increases leftward and y increases upward. The page function allows this, but there are two caveats. First, you should make your world domains as large as, or larger than, the frame to avoid truncation. Second, inverting the world by making either coordinate decrease, rather than increase, from the upper-left corner of the frame to the lower-right may cause confusion if you want to display text in world coordinates or use viewports (see below). The difficulty with text is that a specific, negative scale factor for line may result in text becoming very small or invisible.

 

For more information about frame coordinates, see the section titled Coordinate systems in Chapter 2, Learning the Basics.

Clipping and viewports

Sometimes it is desirable to limit graphics to a particular region of the frame. Consider Figure 4-7 below, which is identical to Figure 4-6 except the line segment is only drawn when it is more than 130 pixels, in world coordinates, from the edge of the world.

Figure 4-7. This GRAF.PGM output shows a viewport, or clipping region.

One solution is to determine the intersection of the diagonal with the 130-pixel border to get two new endpoints for the line segment. This algorithm is cumbersome because the diagonal may intersect with any two of the borders. The simple solution, supported by the McIDAS-X graphics subsystem, is to use a viewport . Also called a clipping region, a viewport defines a region of the frame outside of which graphics will not appear even if drawn. Like worlds, viewports are defined using page , but with a fifth argument of zero instead of one. Lines 139 to 151 in GRAF.PGM define the above viewport and draws its extent, as shown below.

      if( mccmdint('BOR.DER', 1, 'Border Width', 0, 0,
     &  (w_lrlin-w_ullin)/3, border ).lt. 0 ) return
      v_ullin = w_ullin + border
      v_ulele = w_ulele + border
      v_lrlin = w_lrlin - border
      v_lrele = w_lrele - border
      call page( v_ullin, v_ulele, v_lrlin, v_lrele, SET_VIEW ) 
      if( border .gt. 0 ) then
          call qgdash( old_dash )
          call dshon
          call box( v_ullin, v_ulele, v_lrlin, v_lrele, color )
          if( old_dash .eq. 0 ) call dshoff
      end if

Note that the viewport also clips text. The main use of viewports in McIDAS-X programming is to generate graphical output in regions set by the LINE and ELEM keywords, as is done by the McIDAS-X commands PTLIST and GRDDISP. Some users have written simple, frame-based graphical interfaces that set aside a portion of the frame as a toolbar and use a viewport to prevent meteorological data from plotting there when the rest of the frame is generated.

Listing for GRAF.PGM

  1 C   THIS IS SSEC PROPRIETARY SOFTWARE - ITS USE IS RESTRICTED.
  2 
  3 C *** McIDAS Revision History ***
  4 C *** McIDAS Revision History ***
  5 
  6 C ? GRAF -- Demo of basic McIDAS graphics
  7 C ?   GRAF <keywords>
  8 C ? Parameters:
  9 C ?   (none)
 10 C ? Keywords:
 11 C ?   BORDER   = | border width, in pixels
 12 C ?   COLOR    = | graphics color level
 13 C ?   WORLD    = | mn_lin mn_ele mx_lin mx_ele  to define and
 14 C ?              | activate a world
 15 C ? Remarks
 16 C ?       This demo nominally draws a diagonal line from 
 17 C ?   the upper left to the lower right of the display.
 18 C ?
 19 C ?       If WORLD= arguments are not specified, the initpl()
 20 C ?   default world of 480 lines by 640 elements is defined
 21 C ?   but not activated. The diagonal line will be correct
 22 C ?   only if the display size is 480 by 640. If WORLD= arguments
 23 C ?   are specified the world will be defined and activated and
 24 C ?   the diagonal correct regardless of world size.
 25 C ? 
 26 C ?   BORDER= defines a viewport (clipping region) the indicated
 27 C ?   number of pixels (world coordinates) from the edge of the
 28 C ?   world and outlines it with a dashed line.
 29 C ? ----------
 30       subroutine main0
 31
 32       implicit      NONE
 33
 34 C --- Constants and shared variables
 35
 36       integer       PEN_UP  ! move pen without drawing
 37       integer       SET_VIEW    ! define a viewport
 38       integer       SET_WORLD   ! define a world
 39       parameter            ( PEN_UP = 0, SET_VIEW = 0, SET_WORLD = 1)
 40
 41 C --- local variables
 42
 43       character*80  text        ! output text buffer
 44
 45       integer       border  ! border (view port) width
 46       integer       cele    ! text center element
 47       integer       clin    ! text center line
 48       integer       color   ! color level
 49       integer       frame   ! frame number
 50       integer       f_lrele ! frame lower right element
 51       integer       f_lrlin ! frame lower right line
 52       integer       f_neles ! number of elements in frame
 53       integer       f_nlins ! number of lines in frame
 54       integer       f_ulele ! frame upper left element
 55       integer       f_ullin ! frame upper left line
 56       integer       hgt ! text height
 57       integer       linspac ! spacing between text lines
 58       integer       old_dash    ! dashing mode
 59       integer       sclstat ! scaling (world) mode
 60       integer       v_lrele ! lower left viewport element
 61       integer       v_lrlin ! lower left viewport line
 62       integer       v_ulele ! upper right viewport element
 63       integer       v_ullin ! upper right viewport line
 64       integer       w_lrele ! lower right world element
 65       integer       w_lrlin ! lower right world line
 66       integer       w_ulele ! upper left  world element
 67       integer       w_ullin ! upper left  world line
 68
 69       real      elew2f  ! element frame:world ratio
 70       real      linw2f  ! line frame:world ratio
 71
 72 C --- External functions
 73
 74       integer       luc ! user common peek
 75       integer       mccmdint    ! integer argument fetch
 76       integer       mccmdnum    ! number of args for keyword
 77
 78 C --- Initialized variables
 79
 80       integer       width   ! line width (session current)
 81
 82       data      width  /   0/
 83
 84 C ---------------------------------------------------------------
 85 C INITIALIZE
 86 C ---------------------------------------------------------------
 87
 88 C     // Initialize the plot and fetch the color
 89
 90       frame = luc(-1)
 91       call initpl( frame, width )
 92       if( mccmdint('COL.OR', 1, 'Graphic Color', 3, 1, 3,
 93      &  color ) .lt. 0 ) return
 94
 95 C ---------------------------------------------------------------
 96 C DEFINE THE WORLD AND DRAW BORDER AND DIAGONAL
 97 C ---------------------------------------------------------------
 98
 99 C     // If the user has specified the necessary four arguments to
100 C     // WORLD= read them and define the world; page()
101 C     // automatically activates it.
102 C     // The defaults are 1 1 480 640 but there is no significance
103 C     // to this here; the argfetchers will trigger a return
104 C     // if the user doesn't actually enter a legal value for
105 C     // each of the four positions
106
107       if( mccmdnum('WORLD') .eq. 4 ) then
108           if( mccmdint('WORLD',1, 'World upper left line',
109      &      1, 1, 0, w_ullin ) .lt. 1100 ) return
110           if( mccmdint('WORLD',2, 'World upper left element',
111      &      1, 1, 0, w_ulele ) .lt. 1100 ) return
112           if( mccmdint('WORLD',3, 'World lower right line',
113      &      1, 1, 0, w_lrlin ) .lt. 1100 ) return
114           if( mccmdint('WORLD',4, 'World lower right element',
115      &      1, 1, 0, w_lrele ) .lt. 1100 ) return
116           call page( w_ullin, w_ulele, w_lrlin, w_lrele, SET_WORLD )
117       end if
118
119 C     // get the world definition. Note that there
120 C     // is always a defined world, whether by initpl() or
121 C     // page().
122
123       call world( w_ullin, w_ulele, w_lrlin, w_lrele )
124
125 C     // draw the border and diagonal
126
127       call qgdash( old_dash )
128       call dshoff
129       call box ( w_ullin, w_ulele, w_lrlin, w_lrele, color )
130       call plot( w_ullin, w_ulele, PEN_UP )
131       call plot( w_lrlin, w_lrele, color  )
132       call enpt
133       if( old_dash .ne. 0 ) call dshon
134
135 C ---------------------------------------------------------------
136 C DEFINE THE VIEWPORT AND DRAW BORDER 
137 C ---------------------------------------------------------------
138
139       if( mccmdint('BOR.DER', 1, 'Border Width', 0, 0,
140      &  (w_lrlin-w_ullin)/3, border ).lt. 0 ) return
141       v_ullin = w_ullin + border
142       v_ulele = w_ulele + border
143       v_lrlin = w_lrlin - border
144       v_lrele = w_lrele - border
145       call page( v_ullin, v_ulele, v_lrlin, v_lrele, SET_VIEW )
146       if( border .gt. 0 ) then
147           call qgdash( old_dash )
148           call dshon
149           call box( v_ullin, v_ulele, v_lrlin, v_lrele, color )
150           if( old_dash .eq. 0 ) call dshoff
151       end if
152
153 C ---------------------------------------------------------------
154 C GENERATE AND DISPLAY THE TEXT MESSAGES
155 C ---------------------------------------------------------------
156
157 C     // Fetch the text height and use it and the scale factors
158 C     // to determine the separation between text lines. If the
159 C     // line scale factor is less than one, the text locations
160 C     // will be moved closer together by the scaling but the
161 C     // text height will be unchanged. So increase the separation
162 C     // between lines (in world coordinates) to prevent overwrite.
163
164       if( mccmdint('HGT', 1, 'Text Height', 10, 5, 20,
165      &  hgt ) .lt. 0 ) return
166       call qscale( sclstat )
167       call sclfac( linw2f, elew2f )
168       if( sclstat.eq. 1 .and. linw2f.lt. 1.0 ) then
169           linspac = 1.5*hgt / linw2f
170       else
171           linspac = 1.5*hgt
172       end if
173
174 C     // Determine the center of the topmost five lines.
175 C     // Center the third line in the world; this will illustrate
176 C     // the main use of world coordinates to preserve centering
177 C     // even when display sizes differ.
178
179       call world( w_ullin, w_ulele, w_lrlin, w_lrele )
180       clin = w_ullin + (w_lrlin-w_ullin)/2 - 2*linspac
181       cele = w_ulele + (w_lrele-w_ulele)/2
182
183 C     // Display scaling status.
184
185       call qscale(sclstat)
186       if( sclstat.eq. 1) then
187          text = 'world is ACTIVE'
188       else
189          text = 'world is INACTIVE'
190       end if
191       call plttext( clin, cele, hgt, color, text )
192
193 C     // Get and display frame size.
194
195       call mcfsize( frame, f_nlins, f_neles )
196       f_ullin =                     1
197       f_ulele =                     1
198       f_lrlin = f_nlins + f_ullin - 1
199       f_lrele = f_neles + f_ulele - 1
200       write(text,30) f_ullin, f_ulele, f_lrlin, f_lrele
201   30  format('DISPLAY   ',4I5)
202       clin = clin + linspac
203       call plttext( clin, cele, hgt, color, text )
204
205 C     // Display world size.
206
207       call world( w_ullin, w_ulele, w_lrlin, w_lrele )
208       write(text,32) w_ullin, w_ulele, w_lrlin, w_lrele
209   32  format('WORLD     ',4I5)
210       clin = clin + linspac
211       call plttext( clin, cele, hgt, color, text )
212
213 C     // Display viewport size.
214
215       write(text,34) v_ullin, v_ulele, v_lrlin, v_lrele
216   34  format('VIEWPORT  ',4I5)
217       clin = clin + linspac
218       call plttext( clin, cele, hgt, color, text )
219
220 C ---------------------------------------------------------------
221 C CLEAN-UP
222 C ---------------------------------------------------------------
223
224       call endplt
225
226       call sdest('done',0)
227       return
228       end
229
230
231 ** Name:
232 **  box - draw a box on the display
233 **
234 ** Interface:
235 **  subroutine
236 **  box(integer ullin, integer ulele, integer lrlin,
237 **        integer lrele, integer color)
238 **
239 ** Input:
240 **  ullin    - upper left line
241 **  ulele    - upper left element
242 **  lrlin    - lower right line
243 **  lrele    - lower right element
244 **  color    - color of box
245 **
246 ** Input and Output:
247 **  none
248 **
249 ** Output:
250 **  none
251 **
252 ** Return values:
253 **  none
254 **
255 ** Remarks:
256 **  Input coordinates will be interpreted as either frame or
257 **  world system depending upon whether the caller has activated
258 **  a world or not.
259 **
260 ** Categories: 
261 **  graphic 
262
263       subroutine box( ullin, ulele, lrlin, lrele, color )

264
265       implicit      NONE
266
267 C --- interface variables
268
269       integer       ullin
270       integer       ulele
271       integer       lrlin
272       integer       lrele
273       integer       color
274
275 C --- symbolic constants and shared values
276
277       integer       PEN_UP  ! move pen without drawing
278       parameter            ( PEN_UP = 0)
279
280
281       call plot( ullin, ulele, PEN_UP )
282       call plot( ullin, lrele, color  )
283       call plot( lrlin, lrele, color  )
284       call plot( lrlin, ulele, color  )
285       call plot( ullin, ulele, color  )
286       call enpt
287
288       return
289       end
290
291 ** Name:
292 **  plttext - Center a line of text on the indicated location
293 **
294 ** Interface:
295 **  subroutine
296 **  plttext(integer clin, integer cele, integer hgt,
297 **        integer color, character*(*) text)
298 **
299 ** Input:
300 **  clin    - center line
301 **  cele    - center element
302 **  hgt     - text height
303 **  color   - text color
304 **  text    - text string
305 **
306 ** Input and Output:
307 **  none
308 **
309 ** Output:
310 **  none
311 **
312 ** Return values:
313 **  none
314 **
315 ** Remarks:
316 **  The text will be centered on (clin,cele) in either world
317 **  or frame coordinates, depending upon whether the caller has
318 **  activated a world or not. If a world is active, the actual
319 **  text will be enlarged if the world is smaller than the frame.
320 **  If the world is larger, the text size will be unchanged.
321 **  In order to keep the text centered, this routine does all
322 **  of its own scaling (using sclhgt and sclpnt) and actually
323 **  writes the text in frame coordinates. The display is then
324 **  returned to the initial state set by the caller.
325 **
326 ** Categories: 
327 **  graphic 
328
329       subroutine plttext( clin, cele, hgt, color, text )

330
331       implicit      NONE
332
333 C --- interface variables
334
335       integer       clin
336       integer       cele
337       integer       hgt
338       integer       color
339       character*(*)     text
340
341 C --- local variables
342       integer       ullin   ! upper left of text (frame)
343       integer       ulele   ! upper left of text (frame)
344       integer       txthgt  ! text height, frame coords
345       integer       txtclin ! text center, frame coords
346       integer       txtcele ! text center, frame coords
347       integer       sclstat ! scaling status
348       integer       nchar   ! number of characters in text
349
350 C --- external functions
351
352       integer       len_trim    ! compute length of text
353
354 C --- Determine the actual (frame coordinates) height of the
355 C --- text. (The use of local variable 'txthgt' is needed to keep
356 C --- plttext()from modifying its inputs.)
357 
358       txthgt = hgt
359       call sclhgt( txthgt )
360
361 C --- Determine the center point in frame coordinates. Because
362 C --- sclpnt() always works whether the world is active or not,
363 C --- make this call only if scaling is actually on.
364
365       call qscale( sclstat )
366       if( sclstat .eq. 1 ) then
367           call sclpnt( clin, cele, txtclin, txtcele )
368       else
369           txtclin = clin
370           txtcele = cele
371       end if
372
373 C --- Determine the length of the text message in characters.
374 C --- This information is then used, together with the actual
375 C --- heights, to compute the upper left corner in frame coordinates.
376       nchar = len_trim( text )
377       ullin = txtclin - txthgt/2
378       ulele = txtcele - txthgt*nchar/2 + txthgt/10
379
380 C --- Display the text. Turn scaling off first (we have figured
381 C --- the text height and location in frame coordinates ourselves,
382 C --- right?) but be sure to restore it to its original state
383 C --- according to the result 'sclstat' of the qscale() call above.
384       call scloff
385       call wrtext( ullin, ulele, txthgt, text, nchar, color )
386       if( sclstat .eq. 1 ) call sclon
387
388       call enpt
389
390       return
391       end
392
393
394 ** Name:
395 **  sclfac - return the world to frame scale factors
396 **
397 ** Interface:
398 **  subroutine
399 **  sclfac(real linw2f, real elew2f)
400 **
401 ** Input:
402 **  none
403 **
404 ** Input and Output:
405 **  none
406 **
407 ** Output:
408 **  linw2f    - number of frame lines    per world line
409 **  elew2f    - number of frame elements per world element
410 **
411 ** Return values:
412 **  none
413 **
414 ** Remarks:
415 **      An increment in world coordinates multiplied by the
416 **  appropriate scale factor will become an increment in
417 **  frame coordinates.
418 **
419 **  This routine also illustrates a helpful design principle:
420 **  if your application needs access to the inner workings of
421 **  a subsystem (in this case a common block), write an access
422 **  routine to extend the API rather than just including the
423 **  common block in your application.
424 **
425 ** Categories: 
426 **  graphic 
427
428       subroutine sclfac( linw2f, elew2f )

429
430       implicit      NONE
431
432 C --- interface variables
433
434       real      linw2f
435       real      elew2f
436
437 C --- constants and shared variables
438
439       integer       ifrm    ! frame number for graphics
440       integer       iwdth   ! line width
441       integer       mnele   ! upper left world element
442       integer       mnlin   ! upper left world line
443       integer       mxele   ! lower right world element
444       integer       mxlin   ! lower right world line
445       integer       sclfg   ! scaling on ?
446       real      scele   ! frame elems per world elem
447       real      sclin   ! frame lines per world line
448
449       common /M0FRACOM/ ifrm, iwdth, mxlin, mnlin, mxele, mnele,
450      &  sclin, scele, sclfg
451
452
453 C     // Implementation is trivial; just capture the common
454 C     // block values in the formal arguments.
455
456       linw2f = sclin
457       elew2f = scele
458
459       return
460       end
461
462 ** Name:
463 **  world - return the world coordinates of display corners
464 **
465 ** Interface:
466 **  subroutine
467 **  world(integer w_ullin, integer w_ulele,
468 **        integer w_lrlin, integer w_lrele )
469 **
470 ** Input:
471 **  none
472 **
473 ** Input and Output:
474 **  none
475 **
476 ** Output:
477 **  w_ullin    - upper left line of world
478 **  w_ulele    - upper left element of world
479 **  w_lrlin    - lower right line of world
480 **  w_lrele    - lower right element of world
481 **
482 ** Return values:
483 **  none
484 **
485 ** Remarks:
486 **  See sclfac() for a design note.
487 **
488 ** Categories: 
489 **  graphic
490
491       subroutine world( w_ullin, w_ulele, w_lrlin, w_lrele)

492
493       implicit      NONE
494
495 C --- interface variables
496
497       integer       w_ullin
498       integer       w_ulele
499       integer       w_lrlin
500       integer       w_lrele
501
502 C --- constants and shared variables
503
504       integer       ifrm    ! frame number for graphics
505       integer       iwdth   ! line width
506       integer       mnele   ! upper left world element
507       integer       mnlin   ! upper left world line
508       integer       mxele   ! lower right world element
509       integer       mxlin   ! lower right world line
510       integer       sclfg   ! scaling on ?
511       real      scele   ! frame elems per world elem
512       real      sclin   ! frame lines per world line
513
514       common /M0FRACOM/ ifrm, iwdth, mxlin, mnlin, mxele, mnele,
515      &  sclin, scele, sclfg
516
517
518 C     // Implementation is trivial; just capture the common
519 C     // block values in the formal arguments.
520
521       w_ullin = mnlin
522       w_ulele = mnele
523       w_lrlin = mxlin
524       w_lrele = mxele
525
526       return
527       end

Contouring gridded fields

The mcgrdcon function computes and draws contours on a grid. Since contour drawing requires navigation, you must make a call to mapdef prior to calling mcgrdcon. The simple example below will draw contours using the value entered with the keyword CINT on the command line. If CINT=0, the mcgrdcon function will compute a contour interval and report it, drawing about 10 contour intervals.

    integer nr          !number of rows
    parameter (nr=22)
    integer nc          !number of columns
    parameter (nc=32)           

    integer color           !color of contours
    integer idash           !line dashing control
    integer iwrap           !wrap contours around edges?
    integer lint            !label interval l
    integer lsize           !size (in pixels) of labels
    integer smooth          !smoothing factor for contouring

    real    cint        !contour interval
    real    grid (nr, nc)       !grid to contour

    double precision dint           !contour interval

    character*80 lfmt           !label format

    external ctcvcf         !external function call for strings
        .
        .
        .
C---pick up cint from command line

    if (mccmddbl (' CIN.T' ,1,'Contour Interval' ,0,-1.D10,1.D10,dint)
     &      .lt. 0) return          !if mccmddbl returns less than
                                        !zero and error has occurred

    cint = sngl (dint)
    
        .      [get grid to contour]
        .      [initialize navigation with mapdef call]
        .

    lsize = 6       !labels are 6 pixels high
    color = 4       !use color 4 (green)
    idash = 0       !dash only negative values
    lint = 4        !label very 4th contour
    lfmt = ' ('''Height = ' ,F6.0,' meters''')' !format statement 
                            !that controls  
                            !how the contour    
                            !labels look
    smooth = 15     !smoothing factor
    iwrap = 0   
        
    iret = mcgrdcon (grid,nr,nc,cint,lsize,color,idash,lint
    &    lfmt,smooth,iwrap,ctcvcf) 

The mcgrdcon function also has the capability to draw at specific contour values if those values are entered in the string table, and the non-numeric string name is entered as the contour interval. For example, if the user enters the two commands below:

Type:
TE TEST1 "540 562 598
GRDDISP ETA/00 PARAM=Z LEV=500 CINT=TEST1 UNIT=DM

An ETA model 500 mb Z field is displayed with contours drawn at 5400, 5620, and 5980 m.

The code that handles this case, taken from grddisp.pgm , is shown below and continued on the next page.

1    C ---  a common block that passes the string name for the external 
2   C      contour intervals to the external function is defined:
3
4           external ctcvcf            !external function call for string
5                                     !table entry
6           .
7           .
8           .
9         common/extcomm/cint      !cint is a character*12 and will
10          .                      !contain the string table entry
11          .                      !holding the contour values
12          .
13
14  C --- when GRDDISP picks up the cint string,
15
16        if (mccmdstr ('CIN.T',1,' X',cint) .lt 0) goto 2000
17
18        n = nchars (cint,begin,end)
19
20        rc = mcstrtodbl (cint (begin:end), dint)
21
22  C --- if cint is not a number, then rc will be <0 and dint will be 
23  C     zero.
24  C     This will be the case if a string table entry is being used to
25  C     set the contour values.
26
27        if (rc.lt.0 .and. dint.eq.0)then
28         intc = lit ('EXT')
29         xint = alit ('EXT')
30        else                       !cint is an integer
31         xint = sngl (dint)
32         intc = ifix (xint)
33        endif
34         .
35         .
36         .
37  C --- The call to mcgrdcon is done after the gridded data have been
38  C      read in from the server. Grid contains floating point data, not 
39  C     the scaled integers as stored in the grid array. Because the
40  C     data is floating point, an I-type format in the lfmt string
41  C     generally will not work.
42   lsize = 6                  !label size is 6 pixels
43   icolor = 4                 !draw in color 4 (green)
44   idash = 0                  !dash negative contours
45   lint = 4                   !label every 4th contour
46   lfmt = ' (''' Height = ',F6.0, ' meters''')' !format statement that
47                                                !controls the contour
48                                                !labels
49
50    ismoth =15
51    iwrap = 0
52    maxlev = 0
53
54  iret=mcgrdcon (grid, nr, nc, xint, lsize, icolor, idash, lint,
55 &            lfmt,ismoth, iwrap, maxlev, ctcvcf)

Wind barbs and wind vectors

The McIDAS-X library provides seven functions for plotting wind direction and speed using wind barbs and also provides a function for plotting vectors. The table below describes these seven functions.

Fortran function

C function

Description

mcplotwind

Mcplotwind

plots wind information using barbs and flags at the designated line/element

mcplotwindnavll

McPlotWindNavLL

plots wind information using flags and barbs at a designated latitude/longitude; wind direction is corrected for projection

mcplotskywind

McPlotSkyWind

plots wind and sky cover information at a designated line/element

mcplotskywindnav

McPlotSkyWindNav

plots wind and sky cover information at a designated line/element; wind direction is corrected for projection

mcplotskywindnavll

McPlotSkyWindNavLL

plots wind and sky cover information at a designated latitude/longitude; wind direction is corrected for projection

mcplotwmocalm

McPlotWMOCalm

plots the WMO calm wind symbol at the designated line/element

pltwnv

 

plots wind information using wind vectors at the designated latitude/longitude

The plotwind functions plot wind speed without converting any units. A wind barb uses triangular flags and long and short lines to represent wind speed. For example, the wind flag here represents approximately 75 knots.

The functions that plot sky cover (mcplotskywind , mcplotskywindnav , mcplotskywindnavll) use the WMO code value for sky cover, which indicates the sky cover in eighths.

The pltwnv function plots wind speed using a vector. The vector length can be proportional to the wind speed or a fixed length. To set a proportional vector length, specify a length less than zero in the call. To set a specify a fixed length, specify a length greater than zero. In addition, a previous call to mapdef is required so the navigation functions accurately compute the wind position and direction.

The example below demonstrates the use of the mcplotwind , mcplotskywindnavll , and pltwnv functions.

subroutine main0
double precision direction      ! wind direction in degrees
double precision speed              ! wind speed in knots
double precision latitude       ! latitude in degrees N 
double precision longitude      ! longitude in degrees W

real latlon(4)                      ! arrays needed by mapdef
integer tvbounds(4)
real navparms(4)

integer length                      ! unit length of wind flag/ 
                                ! vector    
integer color_lev               ! graphics color to use
integer sky_cover               ! sky cover WMO code value
integer frame                       ! current frame number
integer hemisphere              ! hemisphere flag

integer ok

data length/40/
data color_lev/3/
c---Define the wind direction and speed.
direction = 270.0
speed = 27.
frame = luc(-1)
c---Now plot the non-corrected wind flag at line 225, element 130.
c---Note in the display that the direction 270 degrees is plotted
c---straight left-right -- that is, it has not been corrected for
c---the navigation/projection.
hemisphere = 1
ok = mcplotwind(225, 130, length, color_lev, hemisphere,
& direction, speed)
c--- Define a new latitude/longitude for plotting a wind flag
c--- with a corrected angle.  Note that the plotted direction is
c--- correctly shown as an earth-relative 270-degree angle.
latitude = 41.
longitude = 140.
ok = mcplotwindnavll (frame, latitude, longitude, length,
    & color_lev, direction, speed)
c---Now give an example of a wind vector.  Note that this
c---is always corrected for the navigation.  
c---
c---Note that a call to mapdef is required before calling
c---pltwnv; only one call per frame is needed.
ok = mapdef(latlin, tvbounds, 'SAT', navparms)
call pltwnv(nint(speed), nint(direction), 440000, 1400000,
    & color_lev, length)
c---Plot the wind flag and sky cover symbol at 35N 130W. The angle
c---of the wind flag is corrected for the navigation.
latitude = 35.0
longitude = 130.0
sky_cover = 3
ok = mcplotskywindnavll(frame,latitude,longitude,length,
& color_lev, sky_cover, direction, speed)
call endplt
return
end
 

Figure 4-8 shows the results of the above example. For this example, the MAP command below was run to produce the background map in a conformal projection and navigation for the frame.

MAP DEF X LALO LAT=20 45 LON=95 165 SLAT=60 SLON=115 PRO=CONF

Note that wind flag1, generated by the mcplotwind call, makes no angle correction based on the navigation for the map projection. However, wind flag 2, generated by the mcplotwindnavll call, correctly rotates the wind direction relative to the earth to compensate for the map direction. Wind flag 3 was generated by the pltwnv call. Note the preceding mapdef call in the code. Windflag 4, generated by the mcplotskywindnavll, plotted both an angle-corrected wind flag and a sky cover symbol, as if constructing a station model plot.

Figure 4-8. Three wind barbs and a wind vector are plotted on a conformal projection.

Weather Symbols

The McIDAS-X library provides eight functions for plotting weather symbols. The table below describes these eight functions.

Fortran function

C function

Description

mcplotwmoweather

McPlotWMOWeather

plots present weather symbols from WMO code

mcplotwmopastwxmand
mcplotwmopastwxauto

McPlotWMOPastWxMand
McPlotWMOPastWxAuto

plots past weather symbols from WMO manned and automated code

mcplotwmosky

McPlotWMOSky

plots sky cover symbol from WMO code

mcplotwmolow
mcplotwmomid
mcplotwmohigh

McPlotWMOLow
McPlotWMOMid
McPlotWMOHigh

plots cloud symbols for low, middle, and high level clouds from WMO code

mcplotwmopressuretendency

McPlotWMOPressureTendency

plots pressure tendency symbols from WMO code

pltxtn
wxsplt

 

old routines for plotting weather symbols


Display characteristics

The McIDAS-X display is the device used to output image and graphical data. Use the two functions below to inquire about the characteristics of the display.

C function

Fortran function

Description

not available

itrmch

obtains the value of a McIDAS-X display characteristic

Mcfsize

mcfsize

obtains the size of a frame, in lines and elements

As a developer, you should use this information for validating display-related command parameters and for making environment-dependent programming decisions. For example, you can find information about the display type, the minimum and maximum valid color levels, or the number of default display lines and elements.

Both the itrmch and mcfsize functions isolate programs from directly accessing User Common, so you don't need to know the User Common index to find the value of a display characteristic.

Obtaining the value of a display characteristic

Applications use the itrmch function to do the following:

To obtain a value, use the appropriate character string from the table below as the first argument to the function.

Strings ending in a question mark return 1 for true and 0 for false.

Valid itrmch strings

Description

TERMINAL_TYP

terminal display type as an integer literal of four characters, for example: "XWIN"

OPER_SYSTEM

operating system of the current McIDAS-X session on this workstation as an integer literal of four characters, for example: "UNIX"

DSP_LINES

number of default display lines

DSP_ELEMENTS

number of default display elements

MAX_COLORS

maximum color level

MIN_COL_LEV

minimum valid color level

MAX_COL_LEV

maximum valid color level

MX_CUR_SIZ_H

maximum cursor height

MX_CUR_SIZ_W

maximum cursor width

MN_CUR_SIZ_H

minimum cursor height

MN_CUR_SIZ_W

minimum cursor width

GRAY_LEVELS

number of gray levels available

ANNOTAT_SIZE

size of the annotation

DWELL_RATE_K

dwell rate constant

BITS_PER_PIX

number of bits per pixel

IND_GRAPHIC?

Does the display have independent graphics?

VAR_FR_SIZE?

Does the display have variable frame sizes?

DISP_TOGGLE?

Is a display toggle required to show a frame?

ZOOM?

Does the display have zoom capability?

STRETCHING?

Is contrast stretching supported?

CUR_BOX?

Is the box cursor type supported?

CUR_XBOX?

Is the crossbox cursor type supported?

CUR_XHAIR?

Is the crosshair cursor type supported?

CUR_BULL?

Is the bullseye cursor type supported?

CUR_SOLID?

Is the solid box cursor type supported?

The itrmch function can be used to validate user-entered command parameters that relate to a display. The example below is from the ZA command. It exits if the color for the current terminal is out of range. The second argument is no longer used.

  C--Get the number of color levels for the terminal
  C--and see if the user asked for a level out of the
  C--accepted range.

       LEVEL=PP(1,1)
       MAXLVL= ITRMCH('MAX_COL_LEV',-1)
       IF (LEVEL.LT.0 .OR. LEVEL.GT.MAXLVL) THEN
          CALL EDEST('Graphics color invalid ',LEVEL)
          REYTURN
       endif

Obtaining the size of a frame

Frame sizes can vary within a McIDAS-X session. Your applications should never assume a size but instead call the mcfsize function to return the size of a given frame in lines and elements, as shown in the code fragment below.

       integer frame
       integer lines
       integer elems

C--- get size of the frame

       frame=4
       call mcfsize(frame, lines, elems)

C--- upon successful completion, lines and elems will contain
C--- frame 4's screen dimensions

System utilities

The McIDAS-X library provides a group of functions for performing system-related tasks such as:

This section provides descriptions and examples of the functions that you can use in your applications to perform these tasks.

 

For additional information about the functions described in this section, see the online man pages provided with the McIDAS-X software.

String tables

A McIDAS-X string table is a collection of names and associated strings. String tables serve two purposes:

 

Users can run the commands TU, TL, TE, TD and REPEAT to manage string tables and simplify command entry. For information about these commands, see the McIDAS-X Learning Guide and the McIDAS User's Guide.

As a programmer, you will find string tables useful because they can serve as a scratch pad for applications to communicate with each other. One application writes information into a character string and saves it in the table where it is available to all subsequent applications, until either the string is changed or the string table is replaced with another.

Use the three functions below to read from or write to a string table.

Fortran function

Description

lbget

gets a string from the current string table

lbput

writes a string to the current string table

lbputc

forms a character string from a sequence of character tokens and writes it to the string table

Although no separate operation exists to delete a string name from the string table, you can delete a string name using lbput with an argument string consisting of one or more blank characters.

Note that lbputc takes an input array of tokens and concatenates them. The resulting string is then associated with the string name only if it is less than 160 characters long. The lbput function will associate only a single string with the string name, subject to the same 160-character limit.

Limitations

You must observe the following limitations when developing applications that access string tables.

Cautions

String tables provide convenient, global storage for passing information in and out of applications without using the command line, text display or file I/O. Although the technique for implementing a string table is easy, using string tables for passing information between commands is not always desirable. If the applications using string tables do not provide a facility for reinitializing the strings used, unpredictable results may occur during subsequent use of the applications.

Storing or sharing information using the string table functions can make applications more convenient for users if used sparingly and documented clearly. It can just as easily lead to confusion, since a string name can't be protected for an application's exclusive use. Other applications or the user (via the string table editor TE) can modify or delete the string, causing the application relying on that string to behave unpredictably. To minimize the risk of name collisions in the string table, choose an unlikely name for the stored string.

Use the McIDAS-X disk file system if your application needs to save more than a few pieces of information that will be used by other applications at a later time. Use a text file, whenever practical, as it simplifies the editing and viewing of the file and makes debugging your application easier.

Examples

The code segments below demonstrate the McIDAS-X string table API. Sample user-level input, via the TE and ECHO commands, is also provided to show how string table entries can be written to and read from both the command line and within an application.

Reading a string from a string table

The lbget function extracts the contents of a string from within an application and places it in a character variable. If the string table value is longer than the character variable receiving it, the value stored in the character variable is truncated. For example, a user enters the following command from the McIDAS-X Text and Command Window.

TE HITTER "MICKEY MANTLE

The code segment below reads the contents of the string HITTER.

     character*12 string_name     ! name of McIDAS string to
                                  ! extract value from
     character*24 out_string      ! variable to store resulting 
                                  ! value in

     string_name = 'HITTER'
     ok = lbget (string_name, out_string)

     if (ok .lt. 0)then
        goto 999
     endif

c--- upon successful completion the contents of the variable 
c--- out_string will be 'MICKEY MANTLE'

Writing a string to a string table

The lbput function stores the contents of a character string in the current McIDAS-X string table associated with a specified string name, as shown in the code fragment below.

     character*12 string_name     ! name of McIDAS string to
                                  ! place new value in
     character*24 in_string       ! variable to store resulting 
                                  ! value in

     string_name = 'HITTER'
     in_string   = 'Willie Mays'
     ok = lbput (string_name, in_string)

     if (ok .lt. 0)then
        goto 999
     endif

c--- upon successful completion the contents of the McIDAS
c--- string HITTER will be 'Willie Mays'

If a user subsequently runs the following command from the McIDAS-X Text and Command Window:

ECHO "The Greatest Centerfielder of all time was #HITTER

The output displayed on the text screen will appear as shown below.

The Greatest Centerfielder of all time was Willie Mays

Writing character tokens to a string table

The lbputc function allows a user to enter a group of character tokens into one string. The code fragment below demonstrates this function.

     parameter (MAXTOK = 3)
     character*12 string_name     ! name of McIDAS string to 
                                  ! place new value in
     character*12 tokens(MAXTOK)  ! string tokens to write into
                                  ! the McIDAS string 700CLUB

     string_name = '700CLUB'
     tokens(1)   = 'Hank Aaron'
     tokens(2)   = 'and'
     tokens(3)   = 'Babe Ruth'
     ok = lbputc (string_name, MAXTOK, tokens) 
     if (ok .lt. 0)then
        goto 999
     endif

c--- upon successful completion the contents of the McIDAS
c--- string 700CLUB will be 'Hank Aaron and Babe Ruth'

If a user subsequently runs the following command from the McIDAS-X Text and Command Window:

ECHO "#700CLUB are the two greatest sluggers of all time

The output displayed on the text screen will appear as shown below.

Hank Aaron and Babe Ruth are the two greatest sluggers of all time

User Common

McIDAS-X applications run in an environment consisting of both static and dynamic parts.

User Common contains the dynamic state of the session. All processes, including applications, can read and modify User Common. You will use it in applications to alter the display and make the applications interact with each other in predictable ways.

 

For information about the itrmch function, which provides details about the static part of the display, see the section in this chapter titled Display characteristics . For a detailed listing of the contents of User Common, see the file uc.doc in the McIDAS-X source directory.

Positive and negative User Common

User Common is divided into positive and negative regions. You must understand the differences between the two and use the appropriate region so that your applications will behave predictably. Note that each session running on a workstation has its own private copy of User Common.

Negative User Common is initialized when the process chain starts. All subsequent processes inherit negative User Common and any changes made to it by processes in the chain.

Batch files, McBASI scripts, and commands separated from each other by a semicolon on a single command line all initiate a chain. Because each process chain has its own copy, Negative User Common cannot be changed from outside the process chain and changes to it are not visible except to the owning process chain, including the display.

The following sequence of commands illustrates why both positive (instantaneous) and negative (process-dependent) User Common are necessary and how applications use them to achieve predictable interactive behavior. If the user enters the three commands below:

SF 2
IMGDISP EASTS/CONUS STA=MSN BAND=4
SF 4

The first command sets the current frame to 2; the second command requests that the latest GOES-EAST 4 km IR image, centered on Madison, Wisconsin, be displayed on the current frame. Now suppose the user wants to view a graphic already displayed on frame 4, and enters the third command before IMGDISP begins displaying the image. The display immediately switches to frame 4.

What happens to the IMGDISP command trying to display to the current frame? Is the current frame the frame the user intended (frame 2) or the frame presently displayed (frame 4)? The ambiguity is resolved with positive and negative User Common.

When SF 2 changes the appropriate word in User Common, in this case word 51, to 2, the display immediately reflects it. When IMGDISP starts, the display state, including the current frame number 2, is copied into negative User Common. IMGDISP can then examine the appropriate User Common word, in this case -1, to get the frame number that was current when it started. This value is always 2; whereas the true current frame (word 51) changes from 2 to 4 when SF 4 runs.

User Common API functions

The User Common functions are described in the table below.

C function

Fortran function

Description

Mcluc

luc

returns a value from User Common

Mcpuc

puc

changes a value in User Common

The most common error in using these functions is specifying the wrong User Common index value; the second most common error is transposing a new value with the User Common index value in puc and Mcpuc.

The m0glue.h include file has many of the User Common indexes enumerated using #define statements.

Several APIs are provided in addition to the basic Mcluc and Mcpuc functions. They are described in the table below.

C function

Fortran function

Description

McGetGraphicsFrameNumberI

mcgetgraphicsframenumberi

returns the current graphics frame number for an interactive application

McGetImageFrameNumberI

mcgetimageframenumberi

returns the current image frame number for an interactive application

McGetGraphicsFrameNumber

mcgetgraphicsframenumber

returns the current graphics frame number

McSetGraphicsFrameNumber

mcsetgraphicsframenumber

sets the current graphics frame number

McGetImageFrameNumber

mcgetimageframenumber

returns the current image frame

McSetImageFrameNumber

mcsetimageframenumber

sets the current image frame number

McGetMaxImageFrameNumber

mcgetmaximageframenumber

returns the maximum image frame number for the current session

McGetMaxGraphicsFrameNumber

mcgetmaxgraphicsframenumber

returns the maximum graphics frame number for the current session

McIsImageLooping

mcisimagelooping

returns current image looping state

McIsImageFrameOn

mcisimageframeon

returns whether or not the current image frame is visible

McSetImageFrameOn

mcsetimageframeon

sets current image frame to visible

McIsImageConnectedToLoop

mcisimageconnectedtoloop

indicates if the image frames are connected to the looping system

McIsGraphicsLooping

mcisgraphicslooping

returns current graphics looping state

McIsGraphicsFrameOn

mcisgraphicsframeon

returns whether the current graphics frame is visible

McSetGraphicsFrameOn

mcsetgraphicsframeon

sets current graphics frame to visible

McIsGraphicsConnectedToLoop

mcisgraphicsconnectedtoloop

indicates whether the graphics frames are connected to the looping system

McGetStdOutputDevice

mcgetstdoutputdevice

returns the destination device for standard output messages

McGetStdErrorDevice

mcgetstderrordevice

returns the destination device for standard error messages

McGetStdDebugDevice

mcgetstddebugdevice

returns the destination device for standard debug messages

McSetStdOutputDevice

mcsetstdoutputdevice

sets the destination device for standard output messages

McSetStdDebugDevice

mcsetstddebugdevice

sets the destination device for standard debug messages

McSetStdErrorDevice

mcsetstderrordevice

sets the destination device for standard error messages

McIsMcIDASRunning

mcismcidasrunning

indicates whether a McIDAS-X session is active

User Common functions are often used to verify that an item, such as a frame, etc., is within a valid range. The example below, from the MAP command, illustrates the use of one of these functions.

Determining if the current frame is within a valid range

The MAP command fragments below define what the highest numbered image frame is and compares that number to the desired frame to be used in the command.

c--- maximum image frame
     MAX_IMAGE = mcgetmaximageframenumber()
.
.
.
c--- get the current image frame
        def_image_frame = mcgetimageframenumber()

c--- get the user desired frame and check to see if it is
c--- out of range.  Note that the user may not have input
c--- a frame number, in which case the default frame is used.
         status = mccmdint('IMA.GE',1,'Image Frame',def_image_frame,
    &         1,MAX_IMAGE,nfri)
         if( status.lt.0 ) return

Note that mcgetimageframenumber, not mcgetimageframenumberi , determines the current frame. This ensures that the current frame is the one displayed at the time MAP is started, not the frame displayed at the time the above code fragment actually runs.

Restoring the display to its original state

The sample code below performs these three tasks:

Note the use of luc and puc since no other APIs are currently available.

c --- freeze the roam
      roam = luc( 178 )
      call puc( 1, 178 )

c --- connect cursor to mouse
      mouse = luc( 67 )
      call puc( 1, 67 )

<deleted code>

100   continue
      status = mcmoubtn(3, button(1), button(2), line, elem)
      altG = 0
      if(status.eq.2) altG=1
      altQ = 0
      if(status.eq.1) altQ=1

c --- check for program termination
      if( altQ.ne.0 ) then
     call beep(200,100)
           interact = -3
     return
      endif

<deleted code>

      goto 100

<deleted code>

c --- reset the mouse
      call puc( mouse, 67 )

c --- reset the roam
      call puc( roam, 178 )

Starting McIDAS-X commands from applications

When developing an applications program, check to see if a McIDAS-X command performs a needed task. If so, you should start that command from your application rather than duplicating the logic inside your program. If fixes are made to the command, your program will automatically contain the updated information. If keywords are removed from a command, it's your responsibility to make the necessary changes in your calling application.

McIDAS-X commands can run synchronously or asynchronously, with or without extended format.

You can start any McIDAS-X command from an application using the functions defined in the table below.

C function

Fortran function

Description

not available

keyin

starts a command asynchronously with extended format

not available

skeyin

starts a command synchronously with extended format

Mckeyin

mckeyin

starts a command asynchronously

Mcskeyin

mcskeyin

starts a command synchronously

Use the keyin , mckeyin and Mckeyin functions to start commands asynchronously. For example, the McIDAS-X time scheduler, sked , starts user commands asynchronously. If the scheduler started a long-running command synchronously, other scheduled commands couldn't start until that command finished.

Use the skeyin , mcskeyin and Mcskeyin functions to start commands synchronously. Using these functions, the application stops and will not continue until the specified command is done. For example, a user can run the

ERASE command to erase a frame and then run the
IMGDISP command to display an image on that frame. If these applications aren't run synchronously, some of the image load could occur before the ERASE command finishes, erasing part of the image.