This page was created by the IDL library routine `mk_html_help2`.

Last modified: Mon Aug 25 17:13:29 2025.

# Directory Listing of Routines

# external/CDAWlib

- COLORBAR[2]
- COMPARE_MYCDFS
  To compare all record varying variables in two CDF files, and
- LIST_MYSTRUCT[1]
- LIST_MYSTRUCT[2]
- LIST_MYSTRUCT[2]
- LIST_MYSTRUCT[3]
- LIST_MYSTRUCT[4]
- LIST_MYSTRUCT[5]
- LIST_MYSTRUCT[6]
- LIST_MYSTRUCT[7]
- LIST_MYSTRUCT[8]
- TNAXES
  Find nice time axis tics.
- AUDIOMASTER
- AURORAL_IMAGE
  This function plots a 2-dimensional array Z mapped onto a polar
- AXLABEL
  Put previously calculated axis labels onto the screen
- B_LIB
- BREAK_MYSTRING
  Convert a string into a string array given a delimiting character
- CDAWEB_ERRPLOT
  Plot error bars over a previously drawn plot.
- CDAWEB_SKYMAP
- CDAWEB_VELOVECT
- XDISPLAYFILE
  Display an ASCII text file using widgets and the widget manager.
- CDFJSON__DEFINE[1]
- CDFJSON__DEFINE[2]
- CDFJSON__DEFINE[2]
- CDFJSON__DEFINE[3]
- CDFJSON__DEFINE[4]
- CDFJSON__DEFINE[5]
- CNV_MDHMS_SEC[2]
  convert time from the form year, month, day, hour, minute, sec
- CNV_SEC_MDHMS[2]
  Convert the time in seconds of the year to the form month, day
- CNVCOORD
  Convert coordinates from geographic to PACE magnetic or
- CNVTIME[2]
  This provides an alternate entry point to CNV_MDHMS_SEC
- COMBINED_SUBTITLE
- DECODE_CDFEPOCH
  Create a yyyy/mm/dd hh:mm:ss string given a CDF Epoch time
- DT_TM_MAK
  Set up a time and date string from reference JD and offset.
- ECCMLT
  Convert coordinates from geographic to geomagnetic and computes
- ENCODE_CDFEPOCH
  Convert a 'yyyy/mm/dd hh:mm:ss' string into CDF epoch time
- FIND_GAPS
- FLUX_MOVIE
- FUV_MOVIE
- FUV_PTG_MOD
- FUV_READ_EPOCH
  Convert a string into a string array given a delimiting character
- FUV_ROTATION_MATRIX
- JDSELECT
  Select Julian Day array subset by month or weekday.
- LOGLEVELS (FUNCTION)
  Compute default values for logarithmic axis labeling
- MAKEI
  Make a long array with given start and end values and step size.
- MAP_KEYWORDS
- MATCH
  Routine to match values in two vectors.
- MLT
- MONDAY
- MONTHDAYS
  Given a year and month returns number of days in that month.
- MOVIE_IMAGES
- MOVIE_MAP_IMAGES
- MOVIE_SKYMAP
- MOVIE_WIND_MAP
- ORB_MGR
- ORBIT_PLT[1]
- ORBIT_PLT[2]
- ORBIT_PLT[2]
- OVERLAY[1]
- OVERLAY[2]
- PLASMA_MOVIE
- PLOT_FLUXIMAGES
- PLOT_FUV_IMAGES[1]
- PLOT_FUV_IMAGES[2]
- PLOT_IMAGES
- PLOT_MAP_IMAGES[1]
- PLOT_MAP_IMAGES[2]
- PLOT_MAP_IMAGES[2]
- PLOT_MAP_IMAGES[3]
- PLOT_MAP_IMAGES[4]
- PLOT_MAPS
- PLOT_OVER[1]
- PLOT_OVER[2]
- PLOT_PLASMAGRAM
- PLOT_SKYMAP
- PLOT_SPECTROGRAM
- PLOT_STACK
- PLOT_TIMESERIES
- PLOT_TIMETEXT
- PLOT_WIND_MAP
- PLOTMASTER
- PROJECT_SUBTITLE
- READ_MYCDF[1]
- READ_MYCDF[2]
  Return true(1) or false(0) depending on whether or not the
- READ_MYCDF[2]
  Return true(1) or false(0) depending on whether or not the
- READ_MYCDF[3]
  Return a copy of val recast to the requested type. If it is not
- READ_MYCDF[4]
  Return true(1) or false(0) depending on whether or not the
- READ_MYCDF[5]
  Append the 'new' data to the 'old' data using array concatenation.
- READ_MYCDF[6]
  Search the metadata anonymous structure for ISTP 'DEPEND'
- READ_MYCDF[7]
  Search the metadata anonymous structure for ISTP 'COMPONENT'
- READ_MYCDF[8]
  Return the data for the requested variable.
- READ_MYCDF[9]
  Return the value of the requested attribute for the requested variable.
- READ_MYCDF[10]
  To read all of the attribute values for the requested variable, and
- READ_MYCDF[11]
  Check if a particular variable is a 'clone' of another variable.
- READ_MYCDF[12]
  To return all of the attribute names for the requested variable, as
- READ_MYCDF[13]
  To return the total number of variables in the cdf.
- READ_MYCDF[14]
  To return a string array containing the names of all of the
- READ_MYCDF[15]
  Read all data and metadata for given variables, from given CDF
- READ_MYNETCDF[1]
- READ_MYNETCDF[2]
  Return the data for the requested variable.
- READ_MYNETCDF[2]
  Return the value of the requested attribute for the requested variable.
- READ_MYNETCDF[3]
  To read all of the attribute values for the requested variable, and
- READ_MYNETCDF[4]
  To return all of the attribute names for the requested variable, as
- READ_MYNETCDF[5]
  To return the total number of variables in the ncdf.
- READ_MYNETCDF[6]
  To return a string array containing the names of all of the
- READ_MYNETCDF[7]
  Read all data and metadata for given variables, from given NCDF
- RECTIFY_DATA
- SEMIMINMAX
- SPDF_READ_UTILITIES[1]
  Parse and examine the input string. It should be the value of the
- SPDF_READ_UTILITIES[2]
  Search the metadata anonymous structure for ISTP 'DEPEND' attributes.
- SPECTROGRAM
  This function plots a color spectrogram of Z in contiguous or
- SSC_PLOT
- THREE_SIGMA
- TIME_INTERVAL
  Find nice time axis tics. (Based on the routine TNAXES)
- TIMEAXIS_TEXT
  Plot a time axis.
- VECTPLT
- VER
  Plot a vertical line on a graph at specified x value.
- VIRTUAL_FUNCS[1]
- VIRTUAL_FUNCS[2]
  Check that all variables in the original variable list are declared as
- VIRTUAL_FUNCS[2]
- VIRTUAL_FUNCS[3]
- VIRTUAL_FUNCS[4]
- VIRTUAL_FUNCS[5]
- VIRTUAL_FUNCS[6]
- VIRTUAL_FUNCS[7]
- VIRTUAL_FUNCS[8]
- VIRTUAL_FUNCS[9]
- VIRTUAL_FUNCS[10]
- VIRTUAL_FUNCS[11]
- VIRTUAL_FUNCS[12]
- VIRTUAL_FUNCS[13]
- VIRTUAL_FUNCS[14]
- VIRTUAL_FUNCS[15]
- VIRTUAL_FUNCS[16]
- XV_LOOKV_TO_GCI[2]
  Converts the XVIS LOOK vector to GCI coordinates
- COMPUTE_CRDS[2]
  Computes all the variables in the XV_DERIVED_DATA block
- RUNLENGTH
  Give run lengths for array values.
- INTERSECT
  Return the elements common to two given arrays.
- XV_UNDISTORT
  'Warps' a 256 by 256 pixel VIS image to display
- XV_LOOKV_TO_GCI[1]
  Converts the XVIS LOOK vector to GCI coordinates
- XV_GET_PHIS
  Computes the PHI angles at every pixel within an XVIS image.
- XV_GET_ALTLS
  Computes the ALTLS value (altitude at line-of-sight) for every
- VISCAL[1]
  Converts a GCI coordinate into geographic lat,lon,alt (alt=altitude)
- GCI_TO_SZA
  Converts a GCI coordinate into a solar zenith angle
- VISCAL[2]
- VISCAL[2]
  Computes coordinates for one image pixel location
- COMPUTE_CRDS[1]
  Computes all the variables in the XV_DERIVED_DATA block
- DAYGLOW
  Computes percentage parameters for the dayglow subtract
- XV_UNPACK_WHERE
  An often used utility that converts a single value
- INIT_COMPRESSION_TABLES
  Vis images are often compressed and uncompressed. To
- UNPACK
  Uncompress a compressed image
- PACK
  Compress an un- compressed image
- XV_SCALE_COLOR_TABLE
  Fits the color table from the CDF file into the table
- VIS-CAL
  This is the main procedure for processing Polar VIS data
- WRITE_MGIF
  Write an IDL image and color table vectors to a
- XYZMAP
- YMD2DN
  Convert from year, month, day to day number of year.

# Routine Descriptions

## AUDIOMASTER

[Next Routine] [List of Routines]

     NAME: AUDIOMASTER
     PURPOSE: To plot the data given in 1 to 30 anonymous structure of the type
              returned by the read_mycdf function.  This function creates an
              audio file based data on each variable in each input structure.
     CALLING SEQUENCE:
           out = audiomaster (a,[more_structures])
     INPUTS:
           a = structure returned by the read_mycdf procedure.

     KEYWORD PARAMETERS:
       TSTART =  String of the form '1996/01/02 12:00:00' or a DOUBLE CDF_EPOCH
       time that is the desired start time of the plots. Data is clipped or
       padded to conform to this time. Default is the start time of the
       earliest data.

       TSTOP = String of the form '1996/01/02 12:00:00' or a DOUBLE
       CDF_EPOCH time that is the desired stop time of the plots. Data is
       clipped or padded to conform to this time. Default is the stop time of
       the latest data.

       PID
       May be used to customize part of the name of a gif file. The value of
       PID may be either a number or a string and will be inserted in the gif
       file name as follows: Spacecraft_instrument_pid_#.gif. If GIF is not
       set then the plot(s) will be put into an x-window and this keyword is
       ignored.

       OUTDIR
       This keyword indiates the output directory where a gif file will be
       placed. If GIF is set but OUTDIR is not, then the gif file will be put
       in the user's current working directory.GIF

       AUTO
       Set this keyword to use autoscaling instead of the variables SCALEMIN
       and SCALEMAX attribute values. The scales will be set to the min and
       max values of the data, after fill values have been filtered from the
       data (see also NONOISE keyword). If the user wishes to modify variable
       scale values for plotting purposes, you may do so by changing the
       appropriate data structure values, ie. struct.variable.scalemin = 0.0.
       Please use great care in modifying the data structures values since
       they will greatly influence what your plots or listings may look like.

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occurred.
     AUTHOR:
           Ron Yurow, NASA/GSFC/Code 672.0, Dec 13, 1996
     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration. All Rights Reserved.

(See external/CDAWlib/audiomaster.pro)

## AURORAL_IMAGE

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
    	Auroral_Image

     PURPOSE:
    	This function plots a 2-dimensional array Z mapped onto a polar
    	projection, with each point mapped to its corresponding Longitude and
    	Latitude (possible to use three 1-dim arrays also)

     CATEGORY:
    	Graphics

     CALLING SEQUENCE:
    	AURORAL_IMAGE, Z, Lon, Lat

     INPUTS:
    	Z:	2-dimensional data array (nLon, nLat)
    		or 1-dimensional (requires Lon and Lat be defined)
    		(currently assumes Z is always positive)

     OPTIONAL INPUTS:
    	Lon:	Corresponding Longitudes for Z, degrees (-180:+180 deg)
    		1-dimensional data array of size Z(*,0) or 2-dim of size Z(*,*)
    		or 1-dimensional of size Z(*) if Z is 1-dim
    ##### try to handle longitudes 0:360??
    	Lat:	Corresponding Latitudes for Z, degrees (-90:+90 deg)
    		1-dimensional data array of size Z(0,*) or 2-dim of size Z(*,*)
    		or 1-dimensional of size Z(*) if Z is 1-dim
    	Assumes measurements in Z are centered on Lat, Lon values

     KEYWORD PARAMETERS:
    	LOGZ=logZ:	Scale Z data and color scale logarithmically
    	CENTERPOLE=centerPole: Center on nearest pole (overrides centerLonLat)
    	CENTERLONLAT=centerLonLat: Center of polar plot [Lon, Lat], degrees
    	(if centerPole and centerLonLat not provided, center on middle of image)
    	RANGELONLAT=rangeLonLat: Range of Longitude and Latitude, degrees
    	  [minLat, minLon, maxLat, maxLon]  (Lat may be >90 or <-90 and
    	  Lon may be >180 or <-180 for crossing poles and Dateline)
    		default is to plot the whole sphere (Earth)
    	CONTINENTs=continents: switch to plot continent outlines
    	  (requires Lon and Lat in geographic coordinates)
    	TJK added the following on 12/12/2003 for vis lab requirements
           FILL_CONT=fill continental outlines w/ solid color
    	NOGRID=nogrid:	switch to not plot map grid (Lat, Lon lines)
    		default is to plot grid lines (added by request)
    	NLON=nLon: Number of pixels of output image in Longitude dim (def=50)
    	NLAT=nLat: Number of pixels of output image in Latitude dim (def=50)
    		NLon and NLat only used by Map_image and TV
    	MAXVALUE=maxValue: Max value of data to plot; values above are ignored
    	MINVALUE=minValue: Min value of data to plot; values below are ignored
    	FILLVALUE=fillValue: Data with this value are ignored
           NOCOLORBAR=nocolorbar:  Switch to not plot a color bar on right
    		default is to plot colorbar (added by request)
    	CTITLE=ctitle:	String title for colorbar
    	CSCALE=cscale:	scale for colorbar range [min, max]
    	CCHARSIZE=cCharSize:	Character size for axis on color bar
    	ROTATION=rotation: Rotate map, degrees (def=0), positive clockwise
    	TVSCALE=tvScale: Integer scaling factor for TV method only
    	METHOD=method: String indicating which method to plot with:
    	  "TV":		TV bitmap of Z scaled to color table (no map, no plot)
    	  "QUICK":	Quick plotting of Z array only (no map)
    	  "PLOTS":	Use plots command
    	  "POLYFILL":	Use polyfill
    	  "MAPIMAGE":	Use map_image and tv (least preferred method)
    	  "DILATE":	Use convert_coord, dilate and tv
             "MP":         Map Overlay (testing)
    	SLOW=slow: Switch to use bilinear and quintic interpolations (def=0)
    		Only used by Map_image method
    	STATUS=status:  Return 0 if plot okay, else -1 for an error,
    			status variable must be predefined before call
    	PROJ=proj:	Set map projection; defaults to /satellite
    			1=stereo, 2=ortho, 3=cone, 4=lamb, 5=gnom, 6=azim,
    			7=satel, 9=merc, 10=moll, 14=sinu, 15=aitoff
    			Simple cyl proj: 11=8, 12=merc, 13=moll, 18=aitoff
    			use 1, 2, 4, 6, 7 (see IDL manual for more info)
    	ALTITUDE=altitude: Distance from center of sphere in units of sphere's
    			radius (for satellite (7) projection)
    	MAPCOLOR=mapColor: color index for grids and continent overlays;
    			default=white
    	MAPCHARSIZE=mapCharSize: character size for grid numbers; default=1.0
    	_EXTRA=extra:	Any extra parameters to pass on to plot outline
    			  Add your own title, xtitle, ytitle
    		  May be able to over-ride plot location/size with position
    	DEBUG=debug:	switch to print debugging statements
    	NOISOTROPIC=noisotropic: turn off isotropic mapping; default=1 (on)

     OUTPUTS:
    	No outputs.

     COMMON BLOCKS:
    	DEVICETYPEC: deviceType
    	Shared with DeviceOpen.pro to allow inverting grayscale Postscript

     SIDE EFFECTS:
    	Creates plot to screen or file.

     RESTRICTIONS:
    	Sets a specific X margin to allow for the colorbar.

     PROCEDURE:
    	Uses map_set, triangulate, trigrid, map_image to map pixels to polar
    	coordinates; TV to display and map routines to draw grids and continents
    	A colorbar is plotted on the right if not /nocolorbar or cscale is set.

     EXAMPLE:
    	Create a polar plot of 2 dimensional data Z = dist(60), with
    	lat = [findgen(30)+60., 90.-findgen(30)], lon = findgen(60)*6.-180.
    	auroral_image, Z, lon, lat

     MODIFICATION HISTORY:
     	Written by:	Emily A. Greene, Hughes STX, emily@xfiles.gsfc.nasa.gov
    	and Bobby Candey, NASA GSFC Code 632; Robert.M.Candey.1@gsfc.nasa.gov

      $Id: auroral_image.pro 31135 2022-09-24 01:16:23Z nikos $

    	1995 Sept 26	BC, original full copy
    	1995 Sept 29	BC, beta
    	1995 Oct 2	BC, beta 2
    	1995 Nov 3	BC, reversed all Lat and Lon to agree with map_image
    	1996 April 11	BC, cleanup
    	1996 April 16	BC, cleanup, add status
    	1996 April 17	BC, added colorBar to allow autoscale
    	1996 April 18	BC, added methods
    	1996 April 19	BC, added projection keyword and rearranged
    	1996 April 20	BC, added doByteScale function and surface method
    	1996 July 9	BC, added not_nearby, changed centerLonLat calc.
    	1996 July 11	BC, fixed polyfill method, added even scale to quick
    	1996 July 17	BC, cleaned up, added mapColor
    	1996 Aug 5	BC, added comments and removed old stuff
    	1996 Aug 6	BC, added dilate method
       1997 Jul 18 EAG, added avg function, !MAP changed for IDL5
       1997 Aug  6 EAG, added EAG polyfilling method for sparse input image
                              makes circles of radius=radius and removed default
                              circle points if within degrees=degrees of real point
    	1998 Jan 12	BC, added noisotropic keyword

(See external/CDAWlib/auroral_image.pro)

## AXLABEL

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
            AXLABEL

     PURPOSE:
            Put previously calculated axis labels onto the screen
            at proper position. This routine was designed to work
            together with LOGLEVELS to produce fancy log plots.
            It involves several coordinate transformations in order
            to be device independent and take into account the
            character size. The user can specify a label format
            and use 'external' formatting functions similar to
            the [XYZ]TICKFORMAT keyword of PLOT.

     CATEGORY:
            Plotting

     CALLING SEQUENCE:
            AXLABEL,Value [,/XAxis] [,keywords]

     INPUTS:
            VALUE -> A vector with the values to be labelled on the
                 axis.

     KEYWORD PARAMETERS:
            /XAxis -> If set, the labels are placed on the X achis
                 rather than on the Y axis

            /YAxis -> Place the labels on the Y axis (this is the default,
                 and this keyword is there for purely aesthetic reasons)

            CHARSIZE -> The character size of the label

            FORMAT -> An IDL format string (used as argument to the
                  STRING function) or the name of a function that returns
                  formatted labels. This function must accept three
                  arguments, the third of which is the current value
                  (see the online help to [XYZ]TICKFORMAT for more details).
                  AXLABEL always passes 0 to the first two arguments.

            _EXTRA  keywords are passed on to XYOUTS (e.g. COLOR or
                  ORIENTATION). Note that the ALIGN keyword value is
                  determined automatically.

     OUTPUTS:
            Axis labels without fuss.

     SUBROUTINES:
            None.

     REQUIREMENTS:
            A DATA coordinate system must be established by a previous
            PLOT command.

     NOTES:
            AXLABEL currently operates only on the left and bottom axes.

     EXAMPLE:

     MODIFICATION HISTORY:
            mgs, 10 Sep 1999: VERSION 1.00

(See external/CDAWlib/axlabel.pro)

## BREAK_MYSTRING

[Previous Routine] [Next Routine] [List of Routines]

     NAME: BREAK_MYSTRING
     PURPOSE:
           Convert a string into a string array given a delimiting character
     CALLING SEQUENCE:
           out = break_mystring(instring)
     INPUTS:
           instring = input text string
     KEYWORD PARAMETERS:
           delimiter = character to parse by.  Default = ' '
     OUTPUTS:
           out = string array
     AUTHOR:
           Jason Mathews, NASA/GSFC/Code 633,  June, 1994
           mathews@nssdc.gsfc.nasa.gov    (301)286-6879
     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/break_mystring.pro)

## B_LIB

[Previous Routine] [Next Routine] [List of Routines]

     NAME: MAKE_TICK.PRO

     PURPOSE:  Make tick mark on orbit or trace plot

     CALLING SEQUENCE:

      make_tick,lat,lon,symsiz=symsiz,symcol=symcol

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/b_lib.pro)

## CDAWEB_ERRPLOT

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
    	CDAWEB_ERRPLOT

     PURPOSE:
    	Plot error bars over a previously drawn plot.

     CATEGORY:
    	J6 - plotting, graphics, one dimensional.

     CALLING SEQUENCE:
    	CDAWEB_ERRPLOT, Low, High	;X axis = point number.

    	CDAWEB_ERRPLOT, X, Low, High	;To explicitly specify abscissae.

     INPUTS:
    	Low:	A vector of lower estimates, equal to data - error.
    	High:	A vector of upper estimates, equal to data + error.

     OPTIONAL INPUT PARAMETERS:
    	X:	A vector containing the abscissae.

     KEYWORD Parameters:
    	WIDTH:	The width of the error bars, in units of the width of
    	the plot area.  The default is 1% of plot width.

           COLOR: if defined, assign a color to a graph.  If not defined
           the default color will be used.

        FILVAL: The fillval to use to the remove invalid error estimates
        from being plotted.  Optional.

     OUTPUTS:
    	None.

     COMMON BLOCKS:
    	None.

     SIDE EFFECTS:
    	An overplot is produced.

     RESTRICTIONS:
    	Logarithmic restriction removed.

     PROCEDURE:
    	Error bars are drawn for each element.

     EXAMPLES:
    	To plot symmetrical error bars where Y = data values and
    	ERR = symmetrical error estimates, enter:

    		PLOT, Y			;Plot data
    		CDAWEB_ERRPLOT, Y-ERR, Y+ERR	;Overplot error bars.

    	If error estimates are non-symetrical, enter:

    		PLOT,Y
    		CDAWEB_ERRPLOT, Upper, Lower	;Where Upper & Lower are bounds.

    	To plot versus a vector of abscissae:

    		PLOT, X, Y		  ;Plot data (X versus Y).
    		CDAWEB_ERRPLOT, X, Y-ERR, Y+ERR  ;Overplot error estimates.

     MODIFICATION HISTORY:
     Originally errplot.pro, idl internal routine
           RCJ, Feb, 2003     Cdaweb_errplot: Based on errplot (idl internal routine). We needed a
                              'long' loop:  for i=0L,n-1 do begin
           REY, May 20, 2019  Added keyword fillval.

(See external/CDAWlib/cdaweb_errplot.pro)

## CDAWEB_SKYMAP

[Previous Routine] [Next Routine] [List of Routines]

     NAME: CDAWeb_Skymap
     PURPOSE: This Skymap code was given to us by the TWINS project in
     order to properly produce mapped image plots of their TWINS images.

     Modifications: TJK modified it slightly to allow a position to be
     defined, thus allowing it to be used from CDAWeb for making
     thumbnails and larger sized mapped images.  I also changed the name
     of the routine from skymap to cdaweb_skymap, so there's no confusion
     between the two.

     CALLING SEQUENCE: (sample call from below, making large images)

            cdaweb_skymap, image, sc_pos = sc_posv_re_eci_dat[*,(frame-1)], $
              spin_axis=spin_axis_eci_dat[*,(frame-1)], sun_pos=sun_posv_eci_dat[*,(frame-1)], $
              prime_meridian=prime_meridian_eci_dat[*,(frame-1)], lonmin=-88, lonmax=268,latmin=4, $
              latmax=88, colorbar=0, grid = 1,  $
              field=1, limb=1, sphere = 1, mag = mag, term=1, log=0, norotate=1, noerase=1,ctab=39, exobase=0

     INPUTS:
           Required are: image, sc_pos, spin_axis, sun_pos, prime_meridian

     SEE DETAILS BELOW

    ro cdaweb_skymap, image, $
               sc_pos = sc_pos, $
               spin_axis = spin_axis,  $
               prime_meridian=prime_meridian, $
               sun_pos = sun_pos, mag = mag, $
               sphere = sphere, $
               lonmin = lonmin, lonmax = lonmax, $
               latmin = latmin, latmax = latmax,  $
               annotation = annotation, $
               top_annotation = top_annotation, $
               min = min, max = max, $
               grid = grid,  $
               field = field, $
               limb = limb, $
               terminator = terminator,  $
               exobase = exobase, $
               colorbar = colorbar, $
               log = log,  $
               smooth = smooth, $
               norotate = norotate,   $
               xmargin = xmargin, ymargin = ymargin,  $
               title = title, subtitle = subtitle, $
               clip = clip, true = true, $
               square = square,  $
               pathlogo = pathlogo, $
               contour = contour, median = median,  $
               lee = lee, $
               closeup = closeup, xcloseup = xcloseup,  $
               top = top, noerase = noerase, $
               limit = limit, earth = earth,  $
               fullscreen = fullscreen, time = time,  $
               geogrid = geogrid, fill = fill, $
               landcolor = landcolor,  $
               seacolor = seacolor, gei = gei, $
               bartitle = bartitle,  $
               barlevels = barlevels, noimage = noimage,  $
               antiearthward = antiearthward, $
               cbarposition = cbarposition, $
               barcharsize = barcharsize, $
               barformat = barformat,wim=wim, $
               p0lat=p0lat,p0lon=p0lon, $
               rot=rot, $
               annosize=annosize, $
               line_thick=line_thick, $
               ps = ps, $
               ctab=ctab, $
               units = units, $
               sun_spot = sun_spot, $
               label_field_line = label_field_line, $
               position = position, $; TJK add position for support of CDAWeb thumbnails
               thumb=thumb ; TJK add to indicate this is for a small thumbnail plot
    +
     NAME: CDAWEB_SKYMAP.PRO

     PURPOSE:

     Project a lat-lon matrix onto the sphere of the sky and draw the
     earth with field lines.

     CATEGORY:

     CALLING SEQUENCE:
     CDAWEB_SKYMAP, IMAGE

     INPUTS: IMAGE[nlon,nlat] - An image with a column corresponding to
     one latitude and row corresponding to longtitude of the map.

     OPTIONAL INPUTS:

     KEYWORD PARAMETERS:

     SC_POS - A three element array of the S/C postition in some
              geocentric coordinate system.

     SPIN_AXIS - Spin axis direction of the satellite in the same
                 geocentric coordinate system.

     PRIME_MERIDIAN - A 3 element vector that lies in the plane of the
                        sphere pole and the zero reference angle of the
                        sphere equator (the +x axis).  This has nothing
                        to do with the prime meridian of the earth; it is
                        just the most convenient description.

     SUN_POS - The unit vector to the sun in the same system

     MAG - Magnetic dipole direction in the same geocentric system.

     All vectors and positions must be expressed in the same geocentric
     coordinate system.

     SPHERE - Set 0 gives us the full sphere. Set to 1 gives us the
              hemisphere lat and lon 0 deg in the center.

     LATMIN, LATMAX, LONMIN, LONMAX - Same as keywords to MAP_IMAGE.PRO

     ANNOTATION - An array of strings containing information such as time
                  and position, to be output together with the plot in
                  the assigned space.

     MIN - The minimum number on the colorbar.

     MAX - The max number of the color bar

     GRID - If set turns on lat-lon grid in S/C coordinates with the
            'north pole' of the grid (+90 deg) being the spinaxis, and
            lon being the spin angle.

     FIELD - Plots, dipole field lines L=4 and 8 for noon, dusk,
             midnight, and dawn.

     LIMB - If set plots the Earth's limb.

     TERMINATOR - Turns on terminator line

     EXOBASE - If set plots the exobase line (dashed) at 300 km altitude.

     COLORBAR - If set plots a color bar.

     LOG - Turns on logarithmic scaling.

     SMOOTH - Applies a boxcar smoothing function to the mapped (output
              of MAP_IMAGE) image. The purpose is to smooth the visible
              image to aid the eye in interpreting the image as a 3D
              structure and not make the eye unconciously map it to the
              sphere. CAUTION!!: Localized features broadens. Care has to
              be taken when interpreting.

     NOROTATE - Turns off the fancy rotation that make some people
                seasick. If set, spin axis (lat = +90 deg) always points
                up (positive orbit normal down).

     XMARGIN, YMARGIN - Used in MAP_SET (Margin between map and image border)

     TITLE - Inserts title at top of SKYMAP Image

     SUBTITLE - Inserts subtitle under title at top of SKYMAP Image

     CLIP - All values GE than clip are set to 0.

     TRUE - Use TRUE Color representation

     SQUARE - Enable a square format window with minimum space for
              annotation. Default is landscape. The effect of this
              keyword is essentially to put the colorbar in the right
              place (vertically) and annotation under the map. XMARGIN
              and YMARGIN are used to set the position of the map.

     PATHLOGO - The absolut path to a GIF file containing an optional
             pathlogo to be placed. Does not work just yet. Seems that
             calling TVIMAGE the first time makes the position keyword
             not work.

     CONTOUR -'contourimage' is the image that is smoothed and median filtered.
              The CONTOUR procedure puts NLEVELS contours between min_value >
              min(data) and max_value < max(data).

     MEDIAN - Apply the MEDIAN filtering function with a
               nearest-neighbor window. This is applied to the raw
               pixelated image and not the mapped one. This can be used
               together with the SMOOTH keyword but not the LEE
               keyword. The purpose is to clean up statistical noise and
               outliers. CAUTION!!: This function alters the appearance
               of localized features such as the "low-altitude" ENA
               emissions in the IMAGE/HENA data.

     LEE - Apply the LEE filter to the raw image. This can be used
            together with the SMOOTH keyword but not the MEDIAN
            keyword. Should do a better job than MEDIAN but one needs to
            tweak the N and SIG arguments to the LEEFILT.PRO
            function. EXPERIMENTAL!

     CLOSEUP - A shorcut of setting the LIMIT keyword to MAP_SET. This
                gives you automatically 120 x 120 deg FOV. Equal to
                setting LIMIT=[60,-60,-60,60]. Overrides SPHERE.

     XCLOSEUP -A shorcut of setting the LIMIT keyword to MAP_SET. This
                gives you automatically 120 x 120 deg FOV. Equal to
                setting LIMIT= [45, -45, -45, 45]. Overrides SPHERE.

     TOP - Same as for BYTSCL.PRO.

     NOERASE - If set, skymap doesn't erase the previous plot.

     LIMIT - LAT, LON (in degrees)  [LATMIN, LONMIN, LATMAX, LONMAX]

     EARTH - Adds the Earth with landcolor, seacolor, maps out continents

     FULLSCREEN - Eliminates colorbar, annotation.  Entire screen filled
                  by IMAGE

     TIME - Stucture with Year, Doy, Hour, Min, Sec Used with keyword EARTH

     GEOGRID - Used with keyword EARTH

     FILL - Used with keyword EARTH

     LANDCOLOR - Used with keyword EARTH, indicates color of continents

     SEACOLOR - Used with keyword EARTH, indicates color of water

     GEI - Indicates sc_pos (plus other vectors) is in GEI coordinates Used with keyword EARTH

     BARTITLE - Annotation to appear on colorbar, typically Units

     BARLEVELS - Number of divisions in the colorbar.  (divisions + 1) annotations

     NOIMAGE - Indicates that no image should be made

     ANTIEARTHWARD - essentially sets
                     p0lon=180 instead of 0 deg.

     CBARPOSITION - positions colorbar

     BARCHARSIZE - The character size of the color bar annotations.

     BARFORMAT - Format of the Numbers used in the colorbar labeling

     WIM - Passes back the map_image(image) to the calling program

     P0LAT - center of the plot being p0lat, p0lon  in map coordinates

     P0LON - center of the plot being p0lat, p0lon  in map coordinates

     ROT - If not set, then  Rotate the map so that mag dipole axis always points
           upwards.  If set use rot value to rotate the map.

     ANNOSIZE - Size of the text used in the annotation

     LINE_THICK - Thickness of lines used in images

     PS - Indicates whether we are making a postscript image or not
          **Might go away

     CTAB - Indicates which colortable is used to make the image

     UNITS - **Will most likely be replaced by bartitle

     SUN_SPOT - Adds the A, Dot annotation on the plots

     LABEL_FIELD_LINE - Adds 0, 6, 12, 18 labels to the field lines

     OUTPUTS:

       The input image projected onto the sphere of the sky, using the
       azimuthal projection with the 'north pole' of the sky sphere being
       the spin axis. The coordinats of the map are the spin based
       coordinates to represent what a spinning imager 'sees'.

     OPTIONAL OUTPUTS:

     COMMON BLOCKS:
                    None!

     SIDE EFFECTS:

     KNOWN PROBLEMS/BUGS: - Field-line plotting crashes at sc_pos_x=0???

     RESTRICTIONS:

     PROCEDURE:
       Set up the map by, setting 0 deg lat and lon as the
       subsatellite point of the skysphere, i.e. the center of
       the plot. The rotation (ROT argument to MAP_SET) is set
       such that MAG will always point upward on the plot
       window. Points a bit to the side for some positions but
       gives a continuous pointing position of the earth, so
       that it will work if one wants to do a movie. REFLECT_MAP
       is used to mirror turn the map since the map projections
       in IDL are used to put data on the surface of a
       sphere. We want to put data INSIDE a sphere.

       Field lines are plotted for fixed L-shell and MLT range.

     DEPENDENCIES (non-standard IDL routines):

       FIELD_LINE.PRO - To plot field_lines.
       EARTH_BOUNDARY.PRO - To plot Earth's limb.
       TERMINATOR_LINE.PRO - To plot terminator line.
       SPHERE_BASIS.PRO
       DOT.PRO
       SPHERE2SPHERE.PRO
       SPHERE_TO_XYZ.PRO
       XYZ_TO_SPHERE.PRO
       REFLECT_MAP.PRO
       XYTEXT.PRO
       COLORBAR.PRO

     EXAMPLE:
       Following examples lets you view the earth as the
       satellite passes it in a straight trajectory below the
       southpole.

    pro test
      mag = [0, 0, 1]
      sun_pos = [1, 0, 0]
      spin_axis = [-1, 1, 0]
      xs = transpose(interpol([6, -6], 50))
      ys = xs
      zs = transpose(replicate(-2, 50))
      sc_pos = [[xs, ys, zs]]
      for i = 0, 49 do begin
        SKYMAP, dist(10), sc_pos = reform(sc_pos(*, i)), spin_axis = spin_axis,  $
          sun = sun_pos, sphere = 0, mag = mag
        wait, .1
      endfor
    end

     MODIFICATION HISTORY:

           Jun 19 2007, Jillian Redfern, SWRI
           - received new skymap.pro from Pontus Brandt
             incorporating his changes into our version of skymap
           Added in no_sun_spot, ps, line_thick, annosize, ctab  keywords
           Added additional comments to the top of the program

           Mar 22, 2005. Michael Muller, SwRI
           - Commented out overplot of gridlines.

           Dec 06, 2004. Michael Muller, SwRI
           - originally created/tested Nov 07, 2002.
           - Added code to make map of pixels
             so can get values at any x,y grid
             point. Also, overlay/plot the grid.

           Thu Mar 4 09:32:56 2004, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added keyword PRIME_MERIDIAN for plotting the limb.

           Thu Sep 25 15:18:24 2003, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Bug: LATMIN=0 (and some other keywords too) caused
                     latmin to be set to -90, since I used KEYWORD_SET
                     routine. Changed to check set keyowrds with
                     N_ELEMENTS instead.

           Thu Sep 25 15:11:21 2003, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added keywords P0LAT and P0LON to generalize type of display for
                     other instrumental geometries.

           Tue Apr 17 14:21:16 2001, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added MLTs to the tip of each field line
                     plotted. Removed "SUN" annotation.

           Wed Mar 14 18:39:08 2001, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Moved call to COLORBAR last and instead saved system
                     variables from the map coordinate system just after
                     having created it. Restore them again just before
                     exiting this procedure.

           Wed Mar 14 14:40:12 2001, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added keyword CBARPOSITION to have an option to
                     position the colorbar.

           Fri Jan 12 12:55:15 2001, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added keyword ANTIEARTHWARD, which essentially sets
                     p0lon=180 instead of 0 deg. Should carry with it the
                     right LIMIT, but somehow it looks weird for CLOSEUP
                     and XCLOSEUP. Hemisphere and full sphere seems to be
                     fine.

           Fri Jan 12 10:23:02 2001, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added keyword
    		  EARTH: gives outline of earth and continents.
    		  COLOREARTH: gives filled continents.
    		  Positioning and sizing of the earth is NOT solved
    		  yet, in other words, it doesnt work, but have to set
    		  manually in the program! It is EXPERIMENTAL.

           Wed Dec 6 12:48:36 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Adding keyword LIMIT in order to bring the setting
                     of CLOSEUP and XCLOSEUP external to SKYMAP. Keeping
                     old keywords CLOSEUP, XCLOSEUP, SPHERE just in case
                     someone needs to use them.

           Wed Oct 11 08:45:47 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Changed the plotting order to be able to save the
                     data coordinate system established by MAP_SET. Put
                     all plotting not using the data system, first. Still
                     problem with CONTOUR keyword. It is using the data
                     system and shouldnt destroy it, but some how it gets
                     meesed up.

           Thu Sep 28 13:42:27 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added NOERASE keyword. The erasing should be done in
                     here, if any.

           Wed Sep 27 14:05:57 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added TOP keyword to be able to use only a specific
                     region of the colortable.

           Mon Sep 25 10:01:29 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Made filtering possible for 24-bit images.

           Wed Sep 20 07:19:20 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added check if field lines cannot be drawn.

           Tue Sep 19 10:10:30 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added MEDIAN and LEE keywords. Need to tweak their
                     parameters a bit, especially LEE.
                   - Also, set BILINEAR=1 if SMOOTH is set. This soften
                     the edges in the MAP_IMAGE function.

           Wed Sep 6 12:01:07 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added clip keyword. All values GE than clip
                     are set to 0.

           Wed Sep 6 10:00:31 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Fixed format codes for color bar and logscale.

           Thu Jun 15 10:03:09 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added keywords XMARGIN, YMARGIN, and TITLE.

           Thu May 18 19:06:34 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added some keywords for logscale and general looks.

           Fri May 12 18:28:56 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added keyword MAX for the colorbar.

           Tue May 9 11:10:50 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Plotting position of Sun and magnetic north pole.

           Mon May 8 18:07:00 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

    		- Added keyword ANNOTATION.

           Sat Apr 15 16:58:21 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

                   - Included keywords latmin, latmax, lonmin, lonmax.

           Fri Apr 14 13:14:47 2000, Pontus Brandt
           <brandpc1@brandts-pc.jhuapl.edu>

                   - First version done with spin based map ;
                     coordinates. Next step is to have an option for
                     having ; the map coordinates in a geocentric
                     coordinate system ; such as Solar Magnetic
                     coordinates.

(See external/CDAWlib/cdaweb_skymap.pro)

## CDAWEB_VELOVECT

[Previous Routine] [Next Routine] [List of Routines]

     NAME: CDAWEB_VELOVECT
     PURPOSE: To plot a velocity field (uses normalized coords) on a map
     CALLING SEQUENCE:
           cdaweb_velovect,u,v,x,y
     INPUTS:
           u = x component of the 2D field.
           v = y component of the 2D field.
               The vector at point [i,j] has a magnitude of:
    			(U[i,j]^2 + V[i,j]^2)^0.5
    		and a direction of:
    			ATAN2(V[i,j],U[i,j]).
           x = abcissae values, latitudes
           y = ordinate values, longitudes

     KEYWORD PARAMETERS:
           latpass   = Initial latitude of each particular pass
           lonpass   = Initial longitude of each particular pass
           missing   = Missing data value. (fillval)
           length    = Length factor.  The default of 1.0 makes the longest (U,V)
                       vector the length of a cell.
           error     = 0=ok, -1=error occurred
           color     = The color index used for the plot.
         Note:   All other keywords are passed directly to the PLOT procedure
           and may be used to set option such as TITLE, POSITION, NOERASE, etc.

     OUTPUTS:
           None.
     AUTHOR:
           Rita Johnson 12/2004. Based on velovect.pro
     MODIFICATION HISTORY:

(See external/CDAWlib/cdaweb_velovect.pro)

## CDFJSON__DEFINE[1]

[Previous Routine] [Next Routine] [List of Routines]

     Creates a CDFJSON instance

     :KEYWORDS:
       None

      Based on method from IDLffJSON

(See external/CDAWlib/cdfjson__define.pro)

## CDFJSON__DEFINE[2]

[Previous Routine] [Next Routine] [List of Routines]

     Generates a JSON-formatted atom value string from an IDL variable
         An atomic JSON value is a string, number, or true/false/null

     :PARAMS:
       atomValue : in, required, type="NULL, BYTE, STRING, NUMERIC"
          an IDL variable representing the atomic JSON value

     :RETURNS:
       atomString : out, type="STRING"
          a JSON-formatted string representing an atomic JSON value

      Based on method from IDLffJSON

(See external/CDAWlib/cdfjson__define.pro)

## CDFJSON__DEFINE[2]

[Previous Routine] [Next Routine] [List of Routines]

     Generates a JSON value from JSON-formatted string data

     :PARAMS:
       JSONValue : in, required, type="NULL, BYTE, STRING, NUMERIC, HASH, LIST"
          the JSON value to serialize

     :RETURNS:
       JSONString : out, type="STRING"
          a JSON-formatted string

      Based on method from IDLffJSON

(See external/CDAWlib/cdfjson__define.pro)

## CDFJSON__DEFINE[3]

[Previous Routine] [Next Routine] [List of Routines]

     Escapes special characters in JSON formatting

     :PARAMS:
       atomString : in, required
          the JSON string in which to escape special characters

     :RETURNS:
       The string with special characters converted to escape characters.

     :AUTHOR:
          Dawn Lenz, VIS

     :HISTORY:
          16Aug2010:  Dawn Lenz, VIS - Original version

(See external/CDAWlib/cdfjson__define.pro)

## CDFJSON__DEFINE[4]

[Previous Routine] [Next Routine] [List of Routines]

     Returns variable type

     :PARAMS:
       variable : in ,required
          the variable whose type to return

     :AUTHOR:
       Dawn Lenz, VIS

     :HISTORY:
       22Jun2010:  Dawn Lenz, VIS - Original version

(See external/CDAWlib/cdfjson__define.pro)

## CDFJSON__DEFINE[5]

[Previous Routine] [Next Routine] [List of Routines]

     CDFJSON class
         Manages JSON formatting
         Reference:  http://www.json.org

      Only can be used for serialization

      Based on IDLffJSON

(See external/CDAWlib/cdfjson__define.pro)

## CNVCOORD

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
    	CNVCOORD

     PURPOSE:
    	Convert coordinates from geographic to PACE magnetic or
    	from PACE magnetic to geographic

    	calling sequence:
    	  pos = cnvcoord(inpos,[inlong],[height],[/GEO])
    	     the routine can be called either with a 3-element floating
    	     point array giving the input latitude, longitude and height
    	     or it can be called with 3 separate floating point values
    	     giving the same inputs.  The default conversion is from
    	     geographic to PACE geomagnetic coordinates.  If the keyword
    	     GEO is set (/GEO) then the conversion is from magnetic to
    	     geographic.

(See external/CDAWlib/cnvcoord.pro)

## CNVTIME[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
    	CNVTIME

     PURPOSE:
     	This provides an alternate entry point to CNV_MDHMS_SEC

(See external/CDAWlib/cnvtime.pro)

## CNV_MDHMS_SEC[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           CNV_MDHMS_SEC

     PURPOSE:
           convert time from the form year, month, day, hour, minute, sec
           to seconds of the year

     Calling sequence:
    	t = cnv_mdhms_sec(yr, month, day, hour, minute, sec)
    	   if the arguments are arrays, they must be the same size

    	   OR

    	t = cnv_mdhms_sec(time_array)
    	   where time_array is a 2-d intarr (6,n)
    	   the first dimension gives the year, month, day, hour, minute, sec

(See external/CDAWlib/cnv_mdhms_sec.pro)

## CNV_SEC_MDHMS[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
    	CNV_SEC_MDHMS

     PURPOSE:
    	Convert the time in seconds of the year to the form month, day
    	hour, minutes, and seconds

     CALLING SEQUENCE:
    	status = cnv_sec_mdhms(yr, mo, day, hour, minute, sec, yr_secs)

    	All the arguments must be given. yr must be assigned a value (this
    	determines whether you are in  aleap year or not).  Mo, day, hour,
    	minute and sec must be declared to be normal integers and yr_secs
    	must be given a value and must be a long integer.

    	The status will be 0 for success and -1 for failure

(See external/CDAWlib/cnv_sec_mdhms.pro)

## COLORBAR[2]

[Previous Routine] [Next Routine] [List of Routines]

     21 June 1993
     added ccharsize ; 1995 July 26
     added save on !x, !y, !p; 1995 Aug 2; BC
     reduced ncolors when not enough pixels; 1995 Sep 14 BC
     added !p.multi=0; 1996 Aug 28 BC

     Modified: July 30, 1997 by Tami Kovalick added the Reverse Keyword
       so that you can reverse the colors in the colorbar.

     Modified: October 31, 1997 by T. Kovalick added the image keyword -
     this keyword modifies the labeling for the color bar so it indicates
     that values in the image above the scale are assigned to the top color.

     2001 Mar 30 BC, changed fcolor to default to !p.color
     2001 March 30 BC, added nResCol in place of fixed 2 colors

     Purpose:
     This procedure creates a colorbar for the right side of a spectrogram
     and image...

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/Colorbar.pro)

## COMBINED_SUBTITLE

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Combined_SUBTITLE
     PURPOSE: Take a prepared string for both the title and pi line  of the subtitle
     and properly place them on the plot.
     CALLING SEQUENCE:
           project_subtitle, a, pi_list, title, ps=ps
     INPUTS:
           a = variable structure returned from read_mycdf which
    	will be used to determine the project and pi affiliation (only if
    	the pi_list is too short to be believable).
    	title = string to place at the top of the gif.
           pi_list - line containing combine PI's to go at the bottom of the plot file
     OUTPUTS:

     KEYWORD PARAMETERS:

     AUTHOR:
           Tami Kovalick QSS Group Inc.

     MODIFICATION HISTORY: Initial version is a greatly modified version of
     project_subtitle.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/combined_subtitle.pro)

## COMPARE_MYCDFS

[Previous Routine] [Next Routine] [List of Routines]

     NAME: compare_mycdfs
     PURPOSE:
           To compare all record varying variables in two CDF files, and
           to determine if these variables are similarly named, typed, and
           dimensioned.
     CALLING SEQUENCE:
           out = compare_mycdfs(cid1,cid1)
     INPUTS:
           cid1 = the id of a CDF file which has already been opened.
           cid2 = the id of a second CDF file which has already been opened.
     KEYWORD PARAMETERS:
     OUTPUTS:
           out = TRUE/FALSE value indicating if the CDFs are equivalently
                 structured or not.  1 = equivalent, 0 = NOT equivalent
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           11/1/96 R. Burley       Improved the comparison logic, so that
                                   variable order does not matter, and so that
                                   additional non-record-varying variables do
                                   not cause a comparison failure.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/Compare_myCDFs.pro)

## COMPUTE_CRDS[1]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           COMPUTE_CRDS
     PURPOSE:
           Computes all the variables in the XV_DERIVED_DATA block
           for an entire image
     CATEGORY:

     CALLING SEQUENCE:
           Must set up the common block information properly.  This
           routine is tightly integrated into the XVIS package.
     INPUTS:
           None
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
     COMMON BLOCKS:
           numerous
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## COMPUTE_CRDS[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           COMPUTE_CRDS
     PURPOSE:
           Computes all the variables in the XV_DERIVED_DATA block
           for an entire image
     CATEGORY:

     CALLING SEQUENCE:
           Must set up the common block information properly.  This
           routine is tightly integrated into the XVIS package.
     INPUTS:
           None
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           RA and DEC values
     COMMON BLOCKS:
           numerous
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/vis.pro)

## DAYGLOW

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           DAYGLOW
     PURPOSE:
           Computes percentage parameters for the dayglow subtract
           routine
     CATEGORY:

     CALLING SEQUENCE:

     INPUTS:
           SZA == solar zenith angle
           Day == day of year
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           percentages parameterized on solar zenith angles
     COMMON BLOCKS:
           None
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## DECODE_CDFEPOCH

[Previous Routine] [Next Routine] [List of Routines]

     NAME: DECODE_CDFEPOCH
     PURPOSE:
    	Create a yyyy/mm/dd hh:mm:ss string given a CDF Epoch time
     CALLING SEQUENCE:
           out = decode_cdfepoch(e)
     INPUTS:
           e = CDF Epoch timetag (i.e. DOUBLE, millisecs from 0 A.D.)
     KEYWORD PARAMETERS:
     OUTPUTS: out = string in the format 'yyyy/mm/dd hh:mm:ss'
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:

       RCJ Mar/2012 Keywords tt2000 and epoch16 were added

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/decode_CDFEPOCH.pro)

## DT_TM_MAK

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           DT_TM_MAK
     PURPOSE:
           Set up a time and date string from reference JD and offset.
     CATEGORY:
     CALLING SEQUENCE:
           s = dt_tm_mak(jd0, [sec])
     INPUTS:
           jd0 = Julian Date of a reference date (0:00 hr).  in
           sec = Seconds since JD0 at 0:00.                  in
     KEYWORD PARAMETERS:
           Keywords:
             FORMAT = format string.  Allows output date to be customized.
             The default format string is 'Y$ n$ d$ h$:m$:s$ w$'
                The following substitutions take place in the format string:
             Y$ = 4 digit year.
             y$ = 2 digit year.
             N$ = full month name.
             n$ = 3 letter month name.
             0n$= month as a 2 digit number.
             d$ = day of month number.
             0d$= 2 digit day of month number.
             doy$= 3 digit day of year.
             W$ = full weekday name.
             w$ = 3 letter week day name.
             h$ = hour.
             m$ = minute.
             s$ = second.
             f$ = fraction of second (see DECIMAL, DENOMINATOR below).
             I$ = time interval in days to 2 decimal places.
             i$ = time interval in days as an integer.
             H$ = time interval in integer hours.
             @  = Carriage Return.
             !  = Line feed.
            DECIMAL=dp  Number of decimal places to use for fraction of
              second (def=3) for f$ in format.  f$ will include dec pt.
            DENOMINATOR=den If given then fraction is listed as nnn/ddd
              ddd is given by den.  Over-rides DECIMAL keyword.  Ex:
              DENOM=1000 might give 087/1000 for f$ in format.
     OUTPUTS:
           S = resulting string.                             out
     COMMON BLOCKS:
     NOTES:
           Notes: Some examples: 'h$:m$:s$' -> 09:12:04,
             'd$ n$ Y$' -> 12 Jan 1991, 'd$D h$h' -> 3D 2h, ...
     MODIFICATION HISTORY:
           R. Sterner.  17 Nov, 1988.
           Johns Hopkins University Applied Physics Laboratory.
           RES  20 Apr, 1989 --- 2 digit year.
           R. Sterner, 26 Feb, 1991 --- Renamed from time_date_str.pro
           R. Sterner, 27 Feb, 1991 --- Renamed from tm_dt_str.pro
           R. Sterner, 28 Feb, 1991 --- changed format.
           R. Sterner, 17 Jun, 1992 --- fixed a bug for large sec.
           R. Sterner, 27 Sep, 1993 --- Modified to handle arrays.
           R. Sterner,  2 Dec, 1993 --- Slightly modified def format.
           R. Sterner, 1994 Jun 15 --- Added fraction of second.
           R. Sterner, 1995 Mar  8 --- Added i$ format.
           R. Sterner, 1995 Jul  6 --- Added 0d$ format.
           R. Sterner, 1997 Feb  3 --- Added new keywords 0n$ and doy$ to
           give month as 2 digit number and day of year.
           Matthew Savoie, Systems Technology Associates --- 1997 Feb 5
           fixed a bug by adding floor to: days = long(floor(idays)).
           R. Sterner, 1997 Dec 18 --- Added DDECIMAL=ddec for number of
           decimal places in Day of Year.

     Copyright (C) 1988, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/dt_tm_mak.pro)

## ECCMLT

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           ECCMLT

     PURPOSE:
           Convert coordinates from geographic to geomagnetic and computes
           eccentric dipole MLT

           calling sequence:

           pos = eccmlt(year,doy,sod,r,lat,lon)

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/eccmlt.pro)

## ENCODE_CDFEPOCH

[Previous Routine] [Next Routine] [List of Routines]

     NAME: ENCODE_CDFEPOCH
     PURPOSE:
    	Convert a 'yyyy/mm/dd hh:mm:ss' string into CDF epoch time
     CALLING SEQUENCE:
    	e = encode_cdfepoch(instring)
     INPUTS:
           instring = string in the form: 'yyyy/mm/dd hh:mm:ss'
     KEYWORD PARAMETERS:
           epoch16 - if set, the value returned is double complex epoch16
                     value
           tt2000 - if set, the value returned is a 8 byte integer tt200
                    value

                     if not set, return the usual epoch double value
     OUTPUTS:
           e = CDF epoch timetag (i.e. DOUBLE, millisecs since 0 A.D.)
           if /epoch16 set, return an epoch16 value which is a double
           complex.  Newly supported in IDL6.3 and CDF3.1 - added here
           by TJK on 7/19/2006.
           if /tt2000 is set, return a tt2000 value which is an 8 byte
           int.  Newly support in CDF3.3.3 to support leap seconds...
           by TJK 8/22/2011.

     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           8/20/96  : R. Burley     : Modify so that input parameter is not
                                    : changed by this function.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/encode_CDFEPOCH.pro)

## FIND_GAPS

[Previous Routine] [Next Routine] [List of Routines]

     NAME: FIND_GAPS
     PURPOSE: To locate data gaps in an array of Epoch times by searching
              for delta-T's of a given size greater than the average data
              resolution.
     CALLING SEQUENCE:
           gaps = find_gaps(times)
     INPUTS:
           times = array of time tags
     KEYWORD PARAMETERS:
           RATIO    = default gap detection is 2.5 times the average data
                      resolution.  Use this keyword to change the 2.5
     OUTPUTS:
           gaps = array of indices where a gap has been detected.
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 22, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
    	RCJ 03/30/01 Changed 'lt 3' to 'le 3' because this was preventing
    		     the plot of one single data point in some cases

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/find_gaps.pro)

## FLUX_MOVIE

[Previous Routine] [Next Routine] [List of Routines]

     NAME: FLUX_MOVIE
     PURPOSE: To generate mpeg "flux" IMAGE movie files given in the
     input parameter, astruct.

     CALLING SEQUENCE:
           out = flux_movie(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of mpeg file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image
           LIMIT = if set, limit the number of movie frames allowed -
           this is the default for CDAWEB

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
    	Tami Kovalick, Raytheon ITSS, Jan. 2, 2001 - this program is based on the plot_images
    	program originally written by R. Burley.  It is being modified to generate an mpeg movie
    	file.

     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/flux_movie.pro)

## FUV_MOVIE

[Previous Routine] [Next Routine] [List of Routines]

     NAME: FUV_MOVIE

     PURPOSE: Produce mpeg movie from FUV images (WIC, SIE, SIP)

     CALLING SEQUENCE:
           out = fuv_movie(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure used to produce movie.

     KEYWORD PARAMETERS:
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           MPEG      = name of mpeg file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           COLORBAR = calls function to include colorbar w/ image
           LIMIT = if set, limit the number of movie frames allowed -
           this is the default for CDAWEB

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:

           Rita C. Johnson, Jul/2001, based on movie_map_images.pro

     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/fuv_movie.pro)

## FUV_PTG_MOD

[Previous Routine] [Next Routine] [List of Routines]

     NAME: FUV_PTG_MOD

     PURPOSE: calculates geocentric lat,lon, for a complete image

     CALLING SEQUENCE:fuv_ptg_mod,system,vname,time,emis_hgt,gclat,gclon,l0,ras,decl

     INPUTS:
    	image_info_for_instrument:structure which contains all values for
    				  pointing calculation
    	vname: name of the variable in the structure to plot
    	time: time(1)=yyyyddd, time(2)=msec of day
    	emis_hgt: los altitude
     KEYWORD PARAMETERS:
    	geodetic        (set) returns geodetic values if set
    	getra           (set) calculates ra & dec if set
    	ra           (out) right ascension (deg)
    	dec           (out) declination (deg)
    	s           (out) scalar for lpix
    	lpixX           (out) x component of unit look direction
    	lpixY           (out) y component of unit look direction
    	lpixZ           (out) z component of unit look direction
    	posX           (out) x,y,z components of vector from
    	posY           (out)       earth center to emission
    	posZ           (out)
    	versStr           (out) software version string
    	orbpos         (in) hfrey, added 10/23/2000 orb pos in gci.
    	record_number  (in) hfrey, added 10/23/2000 record number.
    	earthlat       (out) hfrey, added 10/23/2000 center of proj.
    	earthlon       (out) hfrey, added 10/23/2000 center of proj.
           instrument	(in) which instrument to calculate
     OUTPUTS:
    	l0		  look direction in gci for central pixel
    	ras		  RA for central pixel
    	decl		  DEC for central pixel
    	gclat           geocentric latitude
    	gclon           geocentric longitude

     MODIFICATION HISTORY:
      this routine is based on the POLAR UVI ptg.pro but was modified for the
    	IMAGE FUV instrument
    	Harald Frey, 01/05/2000
      RCJ, 10/01. Modified to work with CDAWeb s/w
      01/12/10 : hfrey, updated pointing tables, correct table will now be read for SI

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/fuv_ptg_mod.pro)

## FUV_READ_EPOCH

[Previous Routine] [Next Routine] [List of Routines]

     NAME: FUV_READ_EPOCH
     PURPOSE:
           Convert a string into a string array given a delimiting character
     CALLING SEQUENCE:
           fuv_read_epoch,epoch,year,month,day,hour,minute,second,millisecond, $
                  ut,doy,file_stub=file_stub
     INPUTS:
           epoch - value is the number of milliseconds since 01-Jan-0000 00:00:00.000
     KEYWORD PARAMETERS:
           file_stub - I have no idea what this is for. RCJ
     OUTPUTS:
           year, month, day, hour, minute, second, millisecond corresponding to the epoch
    	ut - hours (decimal format) of the day
    	doy - day of year
     AUTHOR:
           Rick Burley
     MODIFICATION HISTORY:
           RCJ 03/2001 - Added the functions fuv_trim2 and 3 to this routine.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/fuv_read_epoch.pro)

## FUV_ROTATION_MATRIX

[Previous Routine] [Next Routine] [List of Routines]

     NAME:			fuv_rotation_matrix
     PURPOSE:		this procedure prepares the rotation matrix which gives
    			the look directions for the IMAGE FUV instruments
     CATEGORY:
     CALLING SEQUENCE:  	transformation_matrix=fuv_rotation_matrix(omega,theta,$
    				phi,scsv_x,scsv_y,scsv_z,sc_x,sc_y,sc_z,psi)

     INPUTS:		omega : instrument roll in degrees, fixed in time
    			theta : instrument tilt in degrees, fixed in time
    			phi   : instrument azimuth in degrees
    			    direction cosines of true spin axis in metal system
    			scsv_x = henry's a
    			scsv_y = henry's b
    			scsv_z = henry's c
     			    direction cosines of true spin axis in inertial
    			    GCI system
    			sc_x = henry's d
    			sc_y = henry's e
    			sc_z = henry's f
    			psi : phase angle in degrees

     OPTIONAL INPUTS:	none
     KEYWORD PARAMETERS:	none
     OUTPUTS:		transformation_matrix
     OPTIONAL OUTPUTS:	none
     COMMON BLOCKS:	none
     SIDE EFFECTS:		none known
     RESTRICTIONS:		we here use the "right mathematical" way of preparing
    			and using a matrix (IDL ##), not the usual IDL way (#)
    			for the moment this looks awful, but provides better
    			comparison with C-code
    			all input vector components have to describe unit
    			vectors and should be given in double precision
     PROCEDURE:
     EXAMPLE:
     SEE ALSO:
     MODIFICATION HISTORY:
     	Written by:	hfrey, using the mathematics developed by H. Heetderks
    	        Date:	January 4, 2000
                           June 4, 2000 transform all angles into radians
           Written by;     rburley, replaced 'stop' statements with return,-1
                           so science data processing is not halted by missing
                           or bad data.
                   Date:   January 9, 2001

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/fuv_rotation_matrix.pro)

## GCI_TO_SZA

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           GCI_TO_SZA
     PURPOSE:
           Converts a GCI coordinate into a solar zenith angle
     CATEGORY:

     CALLING SEQUENCE:
           SAngle = GCI_TO_SZA(Loc)
     INPUTS:
           Pos == a position in GCI coordinates
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           Solar zenith angle in degrees
     COMMON BLOCKS:
           XV_RECORD_DATA
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## INIT_COMPRESSION_TABLES

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           INIT_COMPRESSION_TABLES
     PURPOSE:
           Vis images are often compressed and uncompressed.  To
           do this we create arrays to quickly perform the compression.
     CATEGORY:

     CALLING SEQUENCE:

     INPUTS:
           None
     KEYWORD PARAMETERS:
           None
     OUTPUTS:
           None
     COMMON BLOCKS:
           Sets up the COMPRESSION_TABLES common block variables
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97
    	Rae Dvorsky, March 2014  added code for gain other than 255
           Rae Dvorsky, Dec. 2014   changed ROUND to FIX when making PACK_T

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## INTERSECT

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           INTERSECT
     PURPOSE:
           Return the elements common to two given arrays.
     CATEGORY:
     CALLING SEQUENCE:
           z = intersect(x,y)
     INPUTS:
           x, y = arrays (not necessarily same size).  in
     KEYWORD PARAMETERS:
     OUTPUTS:
           z = array of elements in common.            out
     COMMON BLOCKS:
     NOTES:
           Note: if z is a scalar 0 then no elements were
             in common.
     MODIFICATION HISTORY:
           R. Sterner  19 Mar, 1986.
           R. Sterner, 4 Mar, 1991 --- converted to IDL v2.

     Copyright (C) 1986, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/viscal.pro)

## JDSELECT

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           JDSELECT
     PURPOSE:
           Select Julian Day array subset by month or weekday.
     CATEGORY:
     CALLING SEQUENCE:
           jd_out = jdselect(jd_in, list)
     INPUTS:
           jd_in = Array of potential Julian Days.     in
           list = Text array listing desired values.   in
     KEYWORD PARAMETERS:
           Keywords:
             /MONTH means match months in list.
             /DAY   means match weekdays in list.
     OUTPUTS:
           jd_out = Julian Days that match list.       out
     COMMON BLOCKS:
     NOTES:
           Notes: list consists of either a text array of month
             or weekday names, at least 3 characters long.
             Ex: JD2=jdselect(JD1,/mon,['jan','apr','jul','oct'])
     MODIFICATION HISTORY:
           R. Sterner, 20 May, 1993

     Copyright (C) 1993, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/jdselect.pro)

## LIST_MYSTRUCT[1]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:	remove_excl_pnt

     PURPOSE: remove !N, !E, etc from string, so list labels look better
               Initially written for RBSP data units.

     INPUT: units - string

     OUTPUT: units - cleaned up string

     Example: newunits = remove_excl_pnt('s!E-1!Ncm!E-2!Nster!E-1!NkeV!E-1!N')

    UNCTION remove_excl_pnt, units
    es=strsplit(units,'!',/extract)
    nits=''  ; reset 'units'
    or i=0,n_elements(res)-1 do begin
      res1=strmid(res[i],0,1)  ;  get first character of each part
      case 1 of
        (res1 eq 'N') or (res1 eq 'n'): begin
           len=strlen(res[i])
           units=units+''+strmid(res[i],1,len)
           end
        (res1 eq 'E') or (res1 eq 'e'): begin
    len=strlen(res[i])
    units=units+'^('+strmid(res[i],1,len)+')'
    end
        (res1 eq 'I') or (res1 eq 'i'): begin
    len=strlen(res[i])
    units=units+'_('+strmid(res[i],1,len)+')'
           end
        (res1 eq 'U') or (res1 eq 'u'): begin
    len=strlen(res[i])
    units=units+'^('+strmid(res[i],1,len)+')'
    end
        (res1 eq 'D') or (res1 eq 'd'): begin
    len=strlen(res[i])
    units=units+'_('+strmid(res[i],1,len)+')'
    end
        else: units=units+res[i]
      endcase
    ndfor
    eturn, units
    nd

(See external/CDAWlib/LIST_mystruct.pro)

## LIST_MYSTRUCT[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:	ffo_string - substitute for string()

     PURPOSE: allows override of free format I/O specifications

     INPUT: format - a format specification, value - a value to be string'ed

     Examples: newstring = ffo_string( 'F10.2', 354.9985 )
               newstring = ffo_string( struct.format, struct.dat )

     NOTE: this function wraps the format string in parenthesis

     original version - JWJ 08/08/2000

    UNCTION ffo_string, format, value

     ; First, if format is defined, just use it against the value
     ; and return the result
     if strlen( format ) gt 0 then begin
        ;print, 'ffo_string using given format: string( FORMAT = (' + format + '), value)'
       return, string( FORMAT = '(' + format + ')', value )
     endif

     ; Here's the original reason this function was developed.
     ; If the format is not defined and the data type
     ; is FLOAT, use F13.6 instead of the IDL 5.2 free format
     ; specifier of G13.6 which is causes us particular problems
     if size( value, /type ) eq 4 then begin
       ; print, 'ffo_string overriding free format for FLOAT type: string( FORMAT = (F13.6), value)'
       return, string( FORMAT = '(F13.6)', value )
     endif

     ; At last, if no particular rules were met for overriding the
     ; format specifcation, use the free format I/O
     ; print, 'ffo_string doing free format I/O: string( value )'
     return, string( value )

    nd ; ffo_string

(See external/CDAWlib/LIST_mystruct.pro)

## LIST_MYSTRUCT[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: reform_strc.pro

     PURPOSE: Reforms the data array from a (1,N) to a (N).

     astrc    -  Input structure

    UNCTION reform_strc, astrc
    str=0
    amest=tag_names(astrc)
    s_tags=n_tags(astrc)

    or k=0, ns_tags-1 do begin
      tagname=namest[k]
      names=tag_names(astrc.(k))
      ntags=n_tags(astrc.(k))
      mc=where((names eq 'VAR_NOTES'),nc)
      for j=0, ntags-1 do begin
         if(names[j] eq 'DAT') then begin
            asize=size(astrc.(k).dat)
            if(asize[0] gt 0) then newdata=reform(astrc.(k).dat) else $
                                 newdata=astrc.(k).dat
            tempa=create_struct('DAT',newdata)
            tempb=create_struct(tempb,tempa)
         endif else begin
            str_p=astrc.(k).(j)
            if(j eq 0) then begin
               tempb=create_struct(names[j],str_p)
            endif else begin
               tempa=create_struct(names[j],str_p)
               tempb=create_struct(tempb,tempa)
            endelse
         endelse
      endfor  ; end j
      ; Add VAR_NOTES to each variable that does not have this attribute
      if(mc[0] lt 0) then begin
         tempa=create_struct('VAR_NOTES','')
         tempb=create_struct(tempb,tempa)
      endif
      ; Add each variable to the overall structure
      if(istr eq 0) then begin
         temp2=create_struct(namest[k],tempb)
         b=create_struct(temp2)
      endif else begin
         temp2=create_struct(namest[k],tempb)
         b=create_struct(b,temp2)
      endelse
      istr=istr+1
    ndfor    ; end k

     Free Memory
    pdf_delete, tempa
    pdf_delete, tempb
    pdf_delete, temp2

    eturn, b
    nd

    12/13/2006 - TJK moved parse_mydepend0 out of this file to its own
    file (w/ same name so that it can be called by read_myCDF.pro

(See external/CDAWlib/LIST_mystruct.pro)

## LIST_MYSTRUCT[3]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: reform_mystruc.pro

     PURPOSE: Reforms the data array from a (i,j,k) to a (i*j,k) and (i,j,k,l) to a (i*j*k,l)

     astrc    -  Input structure

    UNCTION reform_mystruct, astrc

    str=0
    amest=tag_names(astrc)
    s_tags=n_tags(astrc)

    or k=0, ns_tags-1 do begin
      sz=size(astrc.(k).dat)
      names=tag_names(astrc.(k))
      ntags=n_tags(astrc.(k))
      ;
      ;
      case sz[0] of
        3: begin
         tagname=namest[k]
         newsz=sz[1]*sz[2]
         newdata=reform(astrc.(k).dat,newsz,sz[3])
         ;astrc.(k).var_notes='ListImage'
         ; RCJ 08/27/2015  Attach var_notes, don't just replace them.
         astrc.(k).var_notes='ListImage. ' + astrc.(k).var_notes
         for j=0, ntags-1 do begin
            if(names[j] eq 'DAT') then begin
               tempa=create_struct('DAT',newdata)
               tempb=create_struct(tempb,tempa)
            endif else begin
               tag_cmd='str_p=astrc.'+tagname+'.(j)'
               if(not execute(tag_cmd)) then begin
                  print, 'ERROR=Execute error setting tag_cmd'
                  close,1
                  return, -1
               endif
               if(j eq 0) then begin
                  tempb=create_struct(names[j],str_p)
               endif else begin
                  tempa=create_struct(names[j],str_p)
                  tempb=create_struct(tempb,tempa)
               endelse
            endelse
         endfor   ; end j
         temp2=create_struct(namest[k],tempb)
         b=create_struct(b,temp2)
        end
        4: begin
         tagname=namest[k]
         newsz=sz[1]*sz[2]*sz[3]
         newdata=reform(astrc.(k).dat,newsz,sz[4])
         ;astrc.(k).var_notes='ListImage3D'
         ; RCJ 08/27/2015  Attach var_notes, don't just replace them.
         astrc.(k).var_notes='ListImage3D. ' + astrc.(k).var_notes
         for j=0, ntags-1 do begin
            if(names[j] eq 'DAT') then begin
               tempa=create_struct('DAT',newdata)
               tempb=create_struct(tempb,tempa)
            endif else begin
               tag_cmd='str_p=astrc.'+tagname+'.(j)'
               if(not execute(tag_cmd)) then begin
                  print, 'ERROR=Execute error setting tag_cmd in reform_mystruct'
                  close,1
                  return, -1
               endif
               if(j eq 0) then begin
                  tempb=create_struct(names[j],str_p)
               endif else begin
                  tempa=create_struct(names[j],str_p)
                  tempb=create_struct(tempb,tempa)
               endelse
            endelse
         endfor   ; end j
         temp2=create_struct(namest[k],tempb)
         b=create_struct(b,temp2)
         ;
        end
        else: begin
         if(istr eq 0) then begin
            b=create_struct(namest[k],astrc.(k))
         endif else begin
            temp=create_struct(namest[k],astrc.(k))
            b=create_struct(b,temp)
         endelse
        end
      endcase
      istr=istr+1
    ndfor

     Free Memory
    pdf_delete, tempa
    pdf_delete, tempb
    pdf_delete, temp

    eturn, b
    nd

(See external/CDAWlib/LIST_mystruct.pro)

## LIST_MYSTRUCT[4]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: ord_mystruc.pro

     PURPOSE: Reorders the given structure so that the dimension of the data
              variables is increasing w/ each entry.

       astrc  -  Input structure
       vorder -  An array of the dimension of each variable in the structure

      RCJ 04/24/2008 Before the structure is reordered,
          look for vars w/ uncertainties associated w/ them, create
          and index and reorder the structure according to this index.
          This will make var and uncertainty be listed side by side.

    UNCTION ord_mystruct, astrc, vorder, is

    len=n_elements(vorder)
    max=max(vorder)
    str=0
    ames=tag_names(astrc)

     RCJ 04/24/2008
     Reorder names so that uncertainties go right next to their respective vars.
     Note: astrc is not being reordered!  only names!  So we also need 'order'

    names=[names[0]]  ; Start w/ Epoch.
    rder=0            ; Position of Epoch in astrc
    or i=1,n_elements(names)-1 do begin
      q=where(nnames eq names[i])
      if q[0] eq -1 then begin  ;  Avoid repeating vars already listed
         nnames=[nnames,names[i]]
         q=where(names eq names[i])
         order=[order,q[0]]
         qq=where(tag_names(astrc.(i)) eq 'DELTA_PLUS_VAR')
         qqq=where(tag_names(astrc.(i)) eq 'DELTA_MINUS_VAR')
         if qq[0] ne -1 and qqq[0] ne -1 then begin
            if astrc.(i).delta_plus_var ne '' then begin
               q=where(names eq strupcase(astrc.(i).delta_plus_var))
        qq=where(nnames eq strupcase(astrc.(i).delta_plus_var))
        ;if q[0] ne -1 then begin  ; if, for whatever reason, this var is not
        if (q[0] ne -1 and qq[0] eq -1) then begin  ; if, for whatever reason, this var is not
           ;  included in the input structure, then skip it; or if it's already
           ; in nnames due to another var
                  nnames=[nnames,strupcase(astrc.(i).delta_plus_var)]
                  order=[order,q[0]]
        endif
            endif
            if astrc.(i).delta_minus_var ne '' and $
               astrc.(i).delta_minus_var ne astrc.(i).delta_plus_var then begin
               q=where(names eq strupcase(astrc.(i).delta_minus_var))
        qq=where(nnames eq strupcase(astrc.(i).delta_minus_var))
               ;if  q[0] ne -1 then begin  ; if, for whatever reason, this var is not
               if (q[0] ne -1 and qq[0] eq -1) then begin  ; if, for whatever reason, this var is not
           ;  included in the input structure, then skip it; or if it's already
           ; in nnames due to another var
           nnames=[nnames,strupcase(astrc.(i).delta_minus_var)]
                  order=[order,q[0]]
        endif
            endif
         endif
      endif
    ndfor

       Need to reorder vorder:
    order=vorder[order]
     RCJ 07/10/2013  RBSP test revealed that 'names' should be ordered too:
    ames=names[order]

    or k=is, vmax do begin
      for i=0, vlen-1  do begin
         if(vorder[i] eq k) then begin
            if(istr eq 0) then begin
               bnew=create_struct(names[i],astrc.(i))
            endif else begin
               temp=create_struct(names[i],astrc.(order[i]))
               bnew=create_struct(bnew,temp)
            endelse
            istr=istr+1
         endif
      endfor   ; end i
    ndfor   ; end k

     Free Memeory
    pdf_delete, temp

    eturn, bnew
    nd

(See external/CDAWlib/LIST_mystruct.pro)

## LIST_MYSTRUCT[5]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: wrt_hybd_strct.pro

     PURPOSE: Prints ascii file of RV or NRV variables

    UNCTION wrt_hybd_strct, a, unit, convar, maxrecs, depend0, mega_num, csv, nvar

     Establish error handler
    atch, error_status
    f(error_status ne 0) then begin
      ;if(error_status eq -96) then $ ; This is Keyword %s not allowed in call to: %s
      ;       print, 'STATUS= This amount of data cannot be listed, please request a shorter time range'
      ;if(error_status eq -133) then $ ; This is Temporary variables are still checked out - cleaning up...
      ;       print, 'STATUS= Incompatible variable types. Select variables separately'
      ;if(error_status eq -124) then $ ; This is Value of %s cannot be NaN
      ;       print, 'STATUS= Temporary memory error. Please try again.'
      ;if(error_status eq -350) then $ ;  This is Unable to obtain current Julian time
      if(error_status eq -360) then $ ;  format has too many elements (idl8.7: -340)
             print, 'STATUS= Please select fewer variables.' $
             else print, 'STATUS= Data cannot be listed'
      print, 'ERROR=Error number: ',error_status,' in listing (wrt_hybd_strct).'
      print, 'ERROR=Error Message: ', !ERR_STRING
      return, -1
    ndif

    tatus=0
    ames=strupcase(tag_names(a))
    tags=n_tags(a)
    lnk='# '

    print, ""
    print, "whats nvar: ", nvar
    print, ""

    print,'convar = ',convar
    ase convar of
      0 : begin
          ; Check MAXRECS
          if(n_elements(num_data) eq 0) then num_data=0
          num_data=num_data+ntags
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             text2='# WARNING: Maxrecs exceeded in Global Attributes; No. Recs. = '
             printf, unit,text,maxrecs
             printf, unit, format='(a,i)',text1,dif_rec
             printf, unit, format='(a)',blnk
             status=1
          endif
          printf, unit, format='("#",14x,"************************************")'
          printf, unit, format='("#",14x,"*****    GLOBAL ATTRIBUTES    ******")'
          printf, unit, format='("#",14x,"************************************")'
          printf, unit, format='("#",14x)'
          for i=0L, ntags-1 do begin
             ;  RCJ 03/18/2014  Space below is arbitrarily defined so each global attr name will fit in that
      ;       space, and could be chopped if too long.
      ;       Needs to be increased if we find longer global attr name. You might need to make changes to ex_prt too.
             ;var='                    '
             var='                              '
             var1=strtrim(names[i],2)
             strput,var,var1,0
             tstsz=size(a.(i))
             if(tstsz[0] eq 0) then begin
                var2=strtrim(a.(i),2)
         ; RCJ 03/18/2014  Clean var2 from carriage-returns, replace w/ blank space:
         var2=strjoin(strsplit(var2,string(10B),/extract),' ')
                slen=strlen(var2)
         ;print,'var2 = ',var2
         ;print,'slen = ',slen
                if(slen gt 80) then begin
                   status=ex_prt(unit,var,var2,slen,0)
                endif else begin
                   ;printf, unit, format='("#",5x,a,5x,a)', var, var2
                   printf, unit, format='("#",5x,a,2x,a)', var, var2
                endelse
             endif else begin
               ;if names[i] eq 'CDAWEB_PARENTS' then begin
               if (names[i] eq 'CDAWEB_PARENTS' or names[i] eq 'PARENTS') then begin
         for k=0L, tstsz[1]-1 do begin
            ;print,'k,tstsz(1) = ',k,' ',tstsz(1)
                   var2=strtrim(a.(i)[k])
            ;print,'var2 = ',var2
                      if(k eq 0) then begin
                         printf, unit, format='("#",5x,a,2x,a)', var, var2
                  ;print,'var, var2 = ',var,' ',var2
                      endif else begin
    	      if k ne tstsz[1]-1 then begin
    	        var3=strtrim(a.(i)[k+1])
                           printf, unit, format='("#",37x,a,2a,a)', var2,', ',var3
    	        k=k+1
                    ;print,'var, var2,k = ',var,' ',var2,' ',k
    	      endif else begin
                           printf, unit, format='("#",37x,a)', var2
    	      endelse
                      endelse
         endfor
        endif else begin ; if not 'cdaweb_parents'
                for k=0L, tstsz[1]-1 do begin
            ;print,'tstsz = ',tstsz
                   var2=strtrim(a.(i)[k])
    	;print,'k, var2 = ',k,' ** ',var2
                   slen=strlen(var2)
                   if(slen gt 80) then begin
                      status=ex_prt(unit,var,var2,slen,k)
                   endif else begin
                      if(k eq 0) then begin
                         ;printf, unit, format='("#",5x,a,5x,a)', var, var2
                         printf, unit, format='("#",5x,a,2x,a)', var, var2
                      endif else begin
                         ;printf, unit, format='("#",30x,a)', var2
                         printf, unit, format='("#",37x,a)', var2
                      endelse
                   endelse
                endfor   ; end k
        endelse
             endelse
          endfor   ; end i
          ;
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             text2='# WARNING: Maxrecs exceeded in Global Attributes; No. Recs. = '
             printf, unit, format='(a)',blnk
             printf, unit, text,maxrecs
             printf, unit, format='(a,i)',text1,dif_rec
             status=1
          endif
          ;
          printf, unit, format='("#",14x)'   ;'(15x)'
          if mega_num gt 1 then printf, unit,'# **************************************************************************************'
          if mega_num gt 1 then printf, unit,'# *********    There is more than one Epoch for the variables selected    **************'
          if mega_num gt 1 then printf, unit,'# *********    Please scroll down                                         **************'
          if mega_num gt 1 then printf, unit,'# **************************************************************************************'
          if mega_num gt 1 then printf, unit, format='("#",14x)'    ;'(15x)'
      end  ; end case 0
      ;
      ; Record Varying Variables
      ;
      1 : begin

          ; Check MAXRECS
          if(n_elements(num_data) eq 0) then num_data=0
          ; Put in appropriate record count
          len=size(a.(0).dat)
          length=len[len[0]+2]
          num_data=length
          ; Check for maxrecs begin exceeded
          num_data=num_data+4
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             printf, unit, text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             printf, unit, format='(a)',blnk
             status=1
             length=maxrecs
          endif

          status=list_header(a,unit,ntags)

          ;labels=strarr(ntags-3)
          ;units=strarr(ntags-3)
          ; RCJ 05/12/2009   Append strings to 'labels' and 'units' instead of presetting the array sizes.
          ; Note that this first value is cut off the array after the array is populated.
          labels=''
          units=''
          ;
          inc=0
          for i=0L, ntags-5 do begin
             ;if (a.(i).var_type eq 'data') or (a.(i).var_type eq 'support_data') then begin
             ;if (a.(i).var_type eq 'data') or ((a.(i).var_type eq 'support_data') and (a.(i).cdfrecvary ne 'NOVARY')) then begin

             if (strlowcase(a.(i).var_type) eq 'data') or ((strlowcase(a.(i).var_type) eq 'support_data') and (a.(i).cdfrecvary ne 'NOVARY')) then begin
                ;;nvar=a.(i).fillval
                ;labels(i)=label_search(a,1,i,0)
         labels=[labels,label_search(a,1,i,0,debug=debug)]
                ;units(i)=a.(i).units
                ;units(i)=unit_search(a,1,i,0)
         units=[units,unit_search(a,1,i,0)]
                ; if 'EPOCH' or 'EPOCH92' etc.
                if(names[i] eq depend0) then begin
                   temp=create_struct(names[i],a.(i).dateph[0])
                endif else begin
                   if(nvar eq 0) then begin
                      temp=create_struct(names[i],a.(i).dat[0])
                   endif else begin
                      temp=create_struct(names[i],a.(i).dat[0:nvar])
                   endelse
                endelse
                if(inc eq 0) then begin
                   b=temp
                endif else begin
                   b=create_struct(b,temp)
                endelse
         inc=inc+1
      endif
          endfor   ; end i
          labels=labels[1:*]
          units=units[1:*]
          ; Free Memory
          spdf_delete, temp
          for j=0L, length-1 do begin
             inc=0
             for i=0L,ntags-5 do begin
                if (strlowcase(a.(i).var_type) eq 'data') or ((strlowcase(a.(i).var_type) eq 'support_data') and (a.(i).cdfrecvary ne 'NOVARY')) then begin
                   ; temporary patch until nvar included as a new variable attribute
                   ;;nvar=a.(i).fillval[0]
                   if(names[i] eq depend0) then begin
                      b.(inc)=a.(i).dateph[j]
    	   inc=inc+1
                   endif else begin
                      if(nvar eq 0) then begin
                         b.(inc)=a.(i).dat[j]
                      endif else begin
                         b.(inc)=a.(i).dat[0:nvar]
                      endelse
    	   inc=inc+1
                   endelse
                endif
             endfor   ; end i

             ;Handle JSON file creation for csv=3
             COMMON SHARE, csv2
             if (csv2 EQ 3) AND (j EQ 0) then begin
               datsize = 0
               jdata_array = []
               for jindex1=0, (n_tags(a)-1) DO BEGIN
                 if (ISA(a.(jindex1), /STRING) NE 1) then if (a.(jindex1).var_type NE 'additional_data') then begin
                   if jdata_array EQ !NULL then jdata_array = [jindex1] else jdata_array = [jdata_array, jindex1] ;Variables to include in JSON listing
                 endif
               endfor
               COMMON SHARE3, cjsonstruct
               COMMON SHARE4, nan_count
               datsize = size(jdata_array, /n_elements) ;Number of variables we want to include in JSON listing
               nan_count=0
               for jindex2=0, (datsize-1) DO BEGIN
                 varattsreached = 'false'
                 jtags = tag_names(a.(jindex2))
                 counter = 0

                 ;Check for NaN in data, then change values to ISTP Standard - CWG 07/09/2019
                 if ISA(a.(jindex2).dat, /STRING) NE 1 then begin
                   if (a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] NE !NULL) AND (nan_count EQ 0) then begin
                     nan_count=1      ;this sared variable will force code to add a section in the listng that will inform user that NaNs were changed for JSON
                   endif

                   ; Set a generic NAN replacer value using the case statement then use that replacer value for both
                   ; data replacement (currently done in the case) and fillvalue substitution.
                   ; Ron Yurow
                   ;typeCDF = a.(jindex2).cdftype
                   ;CASE typeCDF OF
                   ;  'CDF_REAL4': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_REAL8': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_FLOAT' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_DOUBLE' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_BYTE': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -128
                   ;  'CDF_INT1' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -128
                   ;  'CDF_INT2' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -32768
                   ;  'CDF_INT4' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -2147483648
                   ;  'CDF_INT8' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -9223372036854775808
                   ;  'CDF_UINT1' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 255
                   ;  'CDF_UINT2' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 65535
                   ;  'CDF_UINT4' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 4294967295
                   ;  'CDF_EPOCH' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_EPOCH16' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_TIME_TT2000' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -9223372036854775808
                   ;  'CDF_CHAR' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ; 'CDF_UCHAR' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ;  ELSE : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ;ENDCASE

                   ; NaN replacer
                   nan_fillval_replace = 0

                   typeCDF = a.(jindex2).cdftype
                   CASE typeCDF OF
                     'CDF_REAL4': nan_fillval_replace = -1.0E+31
                     'CDF_REAL8': nan_fillval_replace = -1.0E+31
                     'CDF_FLOAT' : nan_fillval_replace = -1.0E+31
                     'CDF_DOUBLE' : nan_fillval_replace = -1.0E+31
                     'CDF_BYTE': nan_fillval_replace = -128
                     'CDF_INT1' : nan_fillval_replace = -128
                     'CDF_INT2' : nan_fillval_replace = -32768
                     'CDF_INT4' : nan_fillval_replace = -2147483648
                     'CDF_INT8' : nan_fillval_replace = -9223372036854775808
                     'CDF_UINT1' : nan_fillval_replace = 255
                     'CDF_UINT2' : nan_fillval_replace = 65535
                     'CDF_UINT4' : nan_fillval_replace = 4294967295
                     'CDF_EPOCH' : nan_fillval_replace = -1.0E+31
                     'CDF_EPOCH16' : nan_fillval_replace = -1.0E+31
                     'CDF_TIME_TT2000' : nan_fillval_replace = -9223372036854775808
                     'CDF_CHAR' : nan_fillval_replace = " "
                     'CDF_UCHAR' : nan_fillval_replace = " "
                     ELSE : nan_fillval_replace = " "
                   ENDCASE

                   a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = nan_fillval_replace

                 endif

                 for ii=0, (n_tags(a.(jindex2))-1) DO BEGIN

                   if jtags[ii] EQ 'FIELDNAM' then varattsreached = 'true'

                   if varattsreached EQ 'true' then begin

    	  ;print, "JEN -- "
    	  ;print,a.(jindex2).varname,'  ',a.(jindex2).cdftype,'  ',a.(jindex2).fillval
    	  ;print, "JEN -- "

                     ; Check to see if the FILLVAL attribute is not finite.  If it is not, then set it
                     ; to the NaN replacement value.
                     ; Ron Yurow
                     IF  jtags[ii] EQ 'FILLVAL' THEN BEGIN
                         IF  ~finite (a.(jindex2).(ii)) THEN a.(jindex2).(ii) = nan_fillval_replace
                     ENDIF

                     if ((a.(jindex2).cdftype EQ 'CDF_EPOCH16') || (a.(jindex2).cdftype EQ 'CDF_EPOCH') || (a.(jindex2).cdftype EQ 'CDF_TIME_TT2000')) then begin ;Convert epochs to iso-8601 for JSON files

    	    ;print,'jtags[ii] = ',jtags[ii]
                       ;if ((jtags[ii] EQ 'VALIDMIN') || (jtags[ii] EQ 'VALIDMAX') || (jtags[ii] EQ 'FILLVAL') || (jtags[ii] EQ 'DAT')) then begin

                       if ((jtags[ii] EQ 'VALIDMIN') || (jtags[ii] EQ 'VALIDMAX') || (jtags[ii] EQ 'DAT')) then begin
                         ;print,TYPENAME(a.(jindex2).(ii))
    	       ;help,a.(jindex2),/str
    	       ;print,'JENSUN1 ***********'
    	       ;help,jtags[ii]
    	       ;help,a.(jindex2).(ii)
    	       ;print,a.(jindex2).(ii)
    	       ;print,'JENSUN1 ***************'

                         if (TYPENAME(a.(jindex2).(ii)) NE 'STRING') then begin

                          epochIso=cdf_epoch_tojuldays(a.(jindex2).(ii), /string)+'Z'

    	       ;print,'epochIso = ',epochIso

                         endif else epochIso=a.(jindex2).(ii)+'Z'
                         jvar = create_struct(jtags[ii], epochIso)
                       endif else jvar = create_struct(jtags[ii], a.(jindex2).(ii))

                     endif else jvar = create_struct(jtags[ii], a.(jindex2).(ii))

                     if (counter EQ 0) then begin
                       varstruct = create_struct(jvar)
                      endif else if (jtags[ii] NE 'DATEPH') then begin
                       varstruct = create_struct(varstruct, jvar)
                      endif

                     counter = counter + 1

                   endif ; varattsreached

                 endfor ; ii=0

                 jdummystruct = create_struct(a.(jindex2).varname+'_', varstruct)

                 if (jindex2 EQ 0) then cjsonstruct = create_struct(jdummystruct) else cjsonstruct = create_struct(cjsonstruct, jdummystruct)
               endfor
             endif
    	       ;print,'epochIso = ',epochIso

             ;Handle CSV file creation
             if keyword_set(csv) AND (csv2 NE 3) then begin
                labsize=n_elements(labels)
                for csvindex=0, (labsize-1) DO BEGIN
                   if (j EQ 0) then begin
                      units[0] = 'yyyy-mm-ddThh:mm:ss.sssZ'
                      labunits = labels+'_'+units
                      tagname1 = 'tagg'+STRTRIM(csvindex,2)
                      if (csvindex LE (labsize-2)) then tmpvar1 = STRTRIM(labunits[csvindex],2)+',' else tmpvar1 = STRTRIM(labunits[csvindex],2)
                      tmpstruc1=create_struct(tagname1,tmpvar1)
                      if (csvindex EQ 0) then newlabs=create_struct(tmpstruc1) else newlabs=create_struct(newlabs,tmpstruc1)
                   endif
                   tagname2 = 'tag'+STRTRIM(csvindex,2)
                   if (csvindex LE (labsize-2)) then tmpvar2=STRTRIM(b.(csvindex),2)+',' else tmpvar2=STRTRIM(b.(csvindex),2)
                   tmpstruc2= create_struct(tagname2, tmpvar2)
                   if (csvindex EQ 0) then begin
                      epoch_iso = a.(0).dat[j]
                      epoch_iso=cdf_epoch_tojuldays(epoch_iso, /string)
                      epoch_iso=epoch_iso+'Z,'
                      tmpvar2=STRTRIM(epoch_iso,2)
                      tmpstruc2= create_struct(tagname2, tmpvar2)
                      newb = create_struct(tmpstruc2)
                   endif else begin
                      newb = create_struct(newb, tmpstruc2)
                   endelse
                endfor
                if (j EQ 0) then begin
                   struclength= n_tags(newlabs)
                   newform = '('+strtrim(struclength,2)+'(A))'
                   printf,unit,format=newform,newlabs
                   cc = strlen(epoch_iso)
                   ; Make sure that we don't write a format element 0 times, IDL
                   ; does not like that.
                   ; Ron Yurow (August 10, 2020)
                   ; newform = '(A'+strtrim(cc,2)+','+strtrim(struclength-1,2)+'(A))'
                   newform = struclength gt 1 ? '(A'+strtrim(cc,2)+','+strtrim(struclength-1,2)+'(A))' : '(A'+strtrim(cc,2)+')'

                endif
                printf, unit, format=newform,newb
             endif else if (csv2 NE 3) then begin
                ;Handle the .txt print statements
                if (j EQ 0) then begin
                  printf,unit,format=a.lform,labels
                  printf,unit,format=a.uform,units
                endif
                printf,unit,format=a.dform,b
             endif

          endfor   ; end j
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='The maximum number of records allowed to be listed is '
             text1='Your request has exceeded this maximum by '
             printf, unit, format='(a)',blnk
             printf, unit, text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             status=1
          endif
          ; Free Memory
          spdf_delete, b
      end   ; end case 1
      ;
      ; Non-Record Varying Variables
      ;
      2 : begin
          ; Check MAXRECS
          if(n_elements(num_data) eq 0) then num_data=0
          ; Put in appropriate record count
          num_data=num_data+4
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='The maximum number of records allowed to be listed is '
             text1='Your request has exceeded this maximum by '
             printf, unit, text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             printf, unit, format='(a)',blnk
             status=1
             length=maxrecs
          endif
          ;
          printf, unit, format='("#",14x,"************************************")'
          printf, unit, format='("#",14x,"**  NON-RECORD VARYING VARIABLES  **")'
          printf, unit, format='("#",14x,"************************************")'
          printf, unit, format='("#",14x)'
      end   ; end case 2
      ;
      ; 2-D Record Varying Variables
      ;
      3 : begin
    Put in a loop to determine the data sizes for each variable's data array
    just once instead of doing this a million times below.  We can't
    trust what's set in a.*.idlsize (at least for virtual variables)
          idlsizes = lonarr(ntags-4,10)
          for i = 0, ntags-5 do begin
              t_size = size(a.(i).dat)
              for j = 0, n_elements(t_size)-1 do begin
                  idlsizes[i,j] = t_size[j]
              endfor
          endfor

          ; Check MAXRECS
          if(n_elements(num_data) eq 0) then num_data=0
          ; Put in appropriate record count
    Use the computed sizes stored in idlsizes above
           len=size(a.(0).dat)
          len=idlsizes[0,*]
          length=len[len[0]+2]
          ; Check for maxrecs begin exceeded
          num_data=length
          num_data=num_data+4
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             printf, unit, text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             printf, unit, format='(a)',blnk
             status=1
             length=maxrecs
          endif

          status=list_header(a,unit,ntags)

          ;;num=a.(0).fillval
          num=nvar
    print, "HELLO, I'm here!!!!!  what's num: ", num
    print, ""

          labels=strarr(num)
          units=strarr(num)
          dep1_values=''
          atags=tag_names(a)
          inc=0L
          for i=0L, ntags-5 do begin
             ;if(a.(i).var_type eq 'data') or (a.(i).var_type eq 'support_data') then begin
             if (strlowcase(a.(i).var_type) eq 'data') or ((strlowcase(a.(i).var_type) eq 'support_data') and (a.(i).cdfrecvary ne 'NOVARY')) then begin
    TJK replace w/ computed size above to improve performance
                 st_sz=size(a.(i).dat)
                 st_sz=idlsizes[i,*]
                if(st_sz[0] le 1) then begin
                   ; Include condition where only 1 time selected w/ num_var
                   ;  length vector
                   if(st_sz[0] eq 1 and st_sz[1] gt 1 and length eq 1) then begin
                      num_var=st_sz[1]
                      for k=0L, num_var-1 do begin
                         labels[inc]=label_search(a,st_sz[0],i,k,debug=debug)
                         ;units(inc)=a.(i).units
    	      units[inc]=unit_search(a,st_sz[0],i,k)
                         ; temp=create_struct(labels(inc),a.(i).dat(k,0))
                         ; temp=create_struct(atags(i)+labels(inc),a.(i).dat(k,0))
    	      unique = strtrim(string(inc), 2)
                         temp=create_struct(atags[i]+unique,a.(i).dat[k,0])
                         if(inc eq 0) then begin
                            b=temp
                         endif else begin
                            b=create_struct(b,temp)
                         endelse
                         inc=inc+1
                      endfor   ; end k
                   endif else begin
                      ;print,'2', inc, size(labels)
                      labels[inc]=label_search(a,st_sz[0],i,0,debug=debug)
    	   ;print,'labels(inc) 1 = ',labels(inc)
                      ;units(inc)=a.(i).units
    	   units[inc]=unit_search(a,st_sz[0],i,0)
    	   ;print,'units(inc) 1 = ',units(inc)
                      ; names[i] eq 'EPOCH' or 'EPOCH92' etc.
                      if(names[i] eq depend0) then begin
                         temp=create_struct(names[i],a.(i).dateph[0])
                      endif else begin
                         temp=create_struct(names[i],a.(i).dat[0])
                      endelse
                      if(inc eq 0) then begin
                         b=temp
                      endif else begin
                         b=create_struct(b,temp)
                      endelse
                      inc=inc+1
                   endelse
                endif   ;  end st_sz[0] le 1
                ;
                if(st_sz[0] eq 2) then begin
                   num_var=st_sz[1]
                      for k=0L, num_var-1 do begin
                         labels[inc]=label_search(a,st_sz[0],i,k,debug=debug)
                         ;units(inc)=a.(i).units
    	      units[inc]=unit_search(a,st_sz[0],i,k)
                         ; temp=create_struct(labels(inc),a.(i).dat(k,0))
                         ;temp=create_struct(atags(i)+labels(inc),a.(i).dat(k,0))
    	      unique = strtrim(string(inc), 2)
                         temp=create_struct(atags[i]+unique,a.(i).dat[k,0])
                         if(inc eq 0) then begin
                            b=temp
                         endif else begin
                            b=create_struct(b,temp)
    	      endelse
    	      ; RCJ 05/19/2003  Added the 'if endif else' above because
    	      ; we got errors when inc=0: b was undefined.
                         ;b=create_struct(b,temp)
                         inc=inc+1
                      endfor
                endif   ; end if st_sz(0) eq 2
                dep1=dependn_search(a,i,1)
                if (dep1[0] ne '') then begin
                   depend1=a.(i).depend_1
                   ; RCJ 05/16/2013  If alt_cdaweb_depend_1 exists, use it instead:
                   q=where(tag_names(a.(i)) eq 'ALT_CDAWEB_DEPEND_1')
                   if (q[0] ne -1) then if (a.(i).alt_cdaweb_depend_1 ne '') then depend1=a.(i).alt_cdaweb_depend_1
                   s=execute('dep1_units=a.'+strtrim(depend1,2)+'.units')
                   dep1=['(@_'+dep1+'_'+dep1_units+')']
                endif
                dep1_values=[dep1_values,dep1]
             endif   ; end a.(i).var_type
          endfor   ; end i
          ; Free Memory
          spdf_delete, temp
          ;
          ; listing depend_1 values if they exist. RCJ 04/01
          ;if (n_elements(dep1_values) gt 1) then begin
             dep1_values=dep1_values[1:*]
          ;   diff=n_elements(labels)-n_elements(dep1_values)
          ;   for k=1,diff do begin
          ;      cmd='space=string("",format="('+strtrim(strlen(labels[k])+1,2)+'x,a)")
          ;      s=execute(cmd)
          ;      dep1_values=[space,dep1_values]
          ;   endfor
          ;endif
          ;
    do this computation once, instead of for each record
    _ntags = ntags-5

          for j=0L, length-1 do begin
             inc=0L
             for i=0L,i_ntags do begin
                ;if(a.(i).var_type eq 'data') or (a.(i).var_type eq 'support_data') then begin
                if ((strlowcase(a.(i).var_type) eq 'data') or (strlowcase(a.(i).var_type) eq 'support_data') and (a.(i).cdfrecvary ne 'NOVARY'))  then begin
                   ; 'EPOCH' or 'EPOCH92'
                   if(names[i] eq depend0) then begin
                      b.(inc)=a.(i).dateph[j]
                      inc=inc+1
                   endif else begin

    TJK 8/24/2009 EXTREMEMLY poor performance
                       st_sz=size(a.(i).dat)
    instead, compute the sizes once above this big loop and reference
    the values here.
                      st_sz = idlsizes[i,*]
                      if(st_sz[0] le 1) then begin
                        if(st_sz[0] eq 1 and st_sz[1] gt 1 and length eq 1) then begin
                            num_var=st_sz[1]
                            for k=0L,num_var-1 do begin
                               b.(inc)=a.(i).dat[k,j]
                               inc=inc+1
                            endfor
                         endif else begin
                            b.(inc)=a.(i).dat[j]
                            inc=inc+1
                         endelse
                      endif
                      if(st_sz[0] eq 2) then begin
                         num_var=st_sz[1]
                            for k=0L,num_var-1 do begin
                               b.(inc)=a.(i).dat[k,j]
                               inc=inc+1
                            endfor
                      endif
                   endelse  ; end  (names(i) ne depend0)
                endif   ; end a.(i).var_type
             endfor   ; end i

              COMMON SHARE, csv2

              if (csv2 EQ 3) AND (j EQ 0) then begin ;Handle JSON file creation for csv=3
                datsize = 0
                jdata_array = []
                for jindex1=0, (n_tags(a)-1) DO BEGIN
                  if (ISA(a.(jindex1), /STRING) NE 1) then if (a.(jindex1).var_type NE 'additional_data') then begin
                    if jdata_array EQ !NULL then jdata_array = [jindex1] else jdata_array = [jdata_array, jindex1] ;Variables to include in JSON listing
                  endif
                endfor
                COMMON SHARE3, cjsonstruct
                COMMON SHARE4, nan_count
                datsize = size(jdata_array, /n_elements) ;Number of variables we want to include in JSON listing
                nan_count=0

                for jindex2=0, (datsize-1) DO BEGIN
                  varattsreached = 'false'
                  jtags = tag_names(a.(jindex2))
                  counter = 0
                  ;Check for NaN in data, then change values to ISTP Standard - CWG 07/09/2019
                  if ISA(a.(jindex2).dat, /STRING) NE 1 then begin
                    if (a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] NE !NULL) AND (nan_count EQ 0) then begin
                      nan_count=1      ;this shared variable will force code to add a section in the listng that will inform user that NaNs were changed for JSON
                    endif

                    ; Set a generic NAN replacer value using the case statement then use that replacer value for both
                    ; data replacement (currently done in the case) and fillvalue substitution.
                    ; Ron Yurow (Dec 3, 2021)
                    ;typeCDF = a.(jindex2).cdftype
                    ;CASE typeCDF OF
                    ; 'CDF_REAL4': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                    ; 'CDF_REAL8': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                    ; 'CDF_FLOAT' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                    ; 'CDF_DOUBLE' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                    ; 'CDF_BYTE': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -128
                    ; 'CDF_INT1' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -128
                    ; 'CDF_INT2' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -32768
                    ; 'CDF_INT4' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -2147483648
                    ; 'CDF_INT8' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -9223372036854775808
                    ; 'CDF_UINT1' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 255
                    ; 'CDF_UINT2' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 65535
                    ; 'CDF_UINT4' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 4294967295
                    ; 'CDF_EPOCH' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                    ; 'CDF_EPOCH16' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                    ; 'CDF_TIME_TT2000' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -9223372036854775808
                    ; 'CDF_CHAR' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                    ; 'CDF_UCHAR' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                    ; ELSE : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                    ;ENDCASE

                    ; NaN replacer
                    nan_fillval_replace = 0

                    typeCDF = a.(jindex2).cdftype
                    CASE typeCDF OF
                      'CDF_REAL4': nan_fillval_replace = -1.0E+31
                      'CDF_REAL8': nan_fillval_replace = -1.0E+31
                      'CDF_FLOAT' : nan_fillval_replace = -1.0E+31
                      'CDF_DOUBLE' : nan_fillval_replace = -1.0E+31
                      'CDF_BYTE': nan_fillval_replace = -128
                      'CDF_INT1' : nan_fillval_replace = -128
                      'CDF_INT2' : nan_fillval_replace = -32768
                      'CDF_INT4' : nan_fillval_replace = -2147483648
                      'CDF_INT8' : nan_fillval_replace = -9223372036854775808
                      'CDF_UINT1' : nan_fillval_replace = 255
                      'CDF_UINT2' : nan_fillval_replace = 65535
                      'CDF_UINT4' : nan_fillval_replace = 4294967295
                      'CDF_EPOCH' : nan_fillval_replace = -1.0E+31
                      'CDF_EPOCH16' : nan_fillval_replace = -1.0E+31
                      'CDF_TIME_TT2000' : nan_fillval_replace = -9223372036854775808
                      'CDF_CHAR' : nan_fillval_replace = " "
                      'CDF_UCHAR' : nan_fillval_replace = " "
                      ELSE : nan_fillval_replace = " "
                    ENDCASE

                    a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = nan_fillval_replace

                  endif

                  for ii=0, (n_tags(a.(jindex2))-1) DO BEGIN
                    if jtags[ii] EQ 'FIELDNAM' then varattsreached = 'true'
                    if varattsreached EQ 'true' then begin

                      ; Check to see if the FILLVAL attribute is not finite.  If it is not, then set it
                      ; to the NaN replacement value.
                      ; Ron Yurow (Dec 3, 2021)
                      IF  jtags[ii] EQ 'FILLVAL' THEN BEGIN
                          IF  ~finite (a.(jindex2).(ii)) THEN a.(jindex2).(ii) = nan_fillval_replace
                      ENDIF

                      if ((a.(jindex2).cdftype EQ 'CDF_EPOCH16') || (a.(jindex2).cdftype EQ 'CDF_EPOCH') || (a.(jindex2).cdftype EQ 'CDF_TIME_TT2000')) then begin ;Convert epochs to iso-8601 for JSON files
                        if ((jtags[ii] EQ 'VALIDMIN') || (jtags[ii] EQ 'VALIDMAX') || (jtags[ii] EQ 'FILLVAL') || (jtags[ii] EQ 'DAT')) then begin
                        ;if ((jtags[ii] EQ 'VALIDMIN') || (jtags[ii] EQ 'VALIDMAX') || (jtags[ii] EQ 'DAT')) then begin

                          if (TYPENAME(a.(jindex2).(ii)) NE 'STRING') then begin
    	       ;help,a.(jindex2),/str
    	       ;print,'JENSUN2 ***********'
    	       ;help,jtags[ii]
    	       ;help,a.(jindex2).(ii)
    	       ;print,a.(jindex2).(ii)
    	       ;print,'JENSUN2 ***************'

                           epochIso=cdf_epoch_tojuldays(a.(jindex2).(ii), /string)+'Z'

    	       ;print,'JENSUN2 ***********'
    	       ;print,"epochIso: ", epochIso
    	       ;print,'JENSUN2 ***************'

                          endif else epochIso=a.(jindex2).(ii)+'Z'
                          jvar = create_struct(jtags[ii], epochIso)
                        endif else jvar = create_struct(jtags[ii], a.(jindex2).(ii))
                      endif else jvar = create_struct(jtags[ii], a.(jindex2).(ii))

                      if (counter EQ 0) then begin
                       varstruct = create_struct(jvar)
                      endif else if (jtags[ii] NE 'DATEPH') then begin
                       varstruct = create_struct(varstruct, jvar)
                      endif
                      counter = counter + 1
                    endif
                  endfor
                  jdummystruct = create_struct(a.(jindex2).varname+'_', varstruct)
                  if (jindex2 EQ 0) then cjsonstruct = create_struct(jdummystruct) else cjsonstruct = create_struct(cjsonstruct, jdummystruct)
                endfor
              endif

              ;Handle CSV file creation
              if keyword_set(csv) AND (csv2 NE 3) then begin
                labsize=n_elements(labels)
                for csvindex=0, (labsize-1) DO BEGIN
                   if (j EQ 0) then begin
                      dep1_size = n_elements(dep1_values)
                      units[0] = 'yyyy-mm-ddThh:mm:ss.sssZ'
                      if dep1_size EQ labsize then labunits = labels+'_'+dep1_values+'_'+units else labunits = labels+'_'+units
                      tagname1 = 'tagg'+STRTRIM(csvindex,2)
                      if (csvindex LE (labsize-2)) then tmpvar1 = STRTRIM(labunits[csvindex],2)+',' else tmpvar1 = STRTRIM(labunits[csvindex],2)
                      tmpstruc1=create_struct(tagname1,tmpvar1)
                      if (csvindex EQ 0) then newlabs=create_struct(tmpstruc1) else newlabs=create_struct(newlabs,tmpstruc1)
                   endif
                   tagname2 = 'tag'+STRTRIM(csvindex,2)
                   if (csvindex LE (labsize-2)) then tmpvar2=STRTRIM(b.(csvindex),2)+',' else tmpvar2=STRTRIM(b.(csvindex),2)
                   tmpstruc2= create_struct(tagname2, tmpvar2)
                   if (csvindex EQ 0) then begin
                      epoch_iso = a.(0).dat[j]
                      epoch_iso=cdf_epoch_tojuldays(epoch_iso, /string)
                      epoch_iso = epoch_iso+'Z,'
                      tmpvar2=STRTRIM(epoch_iso,2)
                      tmpstruc2= create_struct(tagname2, tmpvar2)
                      newb = create_struct(tmpstruc2)
                   endif else begin
                      newb = create_struct(newb, tmpstruc2)
                   endelse
                endfor
                if (j EQ 0) then begin
                   struclength= n_tags(newlabs)
                   newform = '('+strtrim(struclength,2)+'(A))'
                   printf, unit, format=newform,newlabs
                   cc = strlen(epoch_iso)
                   ; Make sure that we don't write a format element 0 times, IDL
                   ; does not like that.
                   ; Ron Yurow (August 10, 2020)
                   ; newform = '(A'+strtrim(cc,2)+','+strtrim(struclength-1,2)+'(A))'
                   newform = struclength gt 1 ? '(A'+strtrim(cc,2)+','+strtrim(struclength-1,2)+'(A))' : '(A'+strtrim(cc,2)+')'
                endif
                printf, unit, format=newform,newb

              endif else if (csv2 NE 3) then begin ;Handle .txt files
                  if (j EQ 0) then begin
                    printf,unit,format=a.lform,labels
                    q=where (dep1_values ne '')
                    if q[0] ne -1  then printf,unit,format=a.dpform,dep1_values
                    printf,unit,format=a.uform,units
                  endif
                  printf,unit,format=a.dform,b
              endif

          endfor   ; end j

          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             printf, unit, format='(a)',blnk
             printf, unit, text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             status=1
             length=maxrecs
          endif
          ; Free Memory
          spdf_delete, b
      end   ;   end case 3
      ;
      ; 3-D Record Varying Variables
      ;
      4 : begin
          ; Check MAXRECS
          if(n_elements(num_data) eq 0) then num_data=0
          ; Put in appropriate record count
          len=size(a.(0).dat)
          length=len[len[0]+2]
          ; Check for maxrecs begin exceeded
          num_data=length
          num_data=num_data+4
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             printf, unit, text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             printf, unit, format='(a)',blnk
             ; printf, unit, ' '
             status=1
             length=maxrecs
          endif
          ;
          printf, unit, format='("#",14x,"************************************")'
          printf, unit, format='("#",14x,"****  RECORD VARYING VARIABLES  ****")'
          printf, unit, format='("#",14x,"************************************")'
          printf, unit, format='("#",14x)'
          printf,unit, format='("# 1. ",a)', a.epoch.fieldnam
          printf,unit, format='("# 2. ",a)', a.index.catdesc
          printf,unit, format='("# 3. ",a)', a.qflag.catdesc
          printf,unit, format='("# 4. ",a)', a.position.fieldnam
          printf,unit, format='("# 5. ",a)', a.vel.fieldnam
          printf,unit,format='("#",14x)'
          ;
          num=7
          labels=strarr(num)
          units=strarr(num)
          inc=0
          ; Epoch
          eplabel='                       '
          strput,eplabel,a.epoch.fieldnam,0
          labels[inc]=eplabel
          units[inc]=a.epoch.units
          temp=create_struct('EPOCH',a.epoch.dateph[0])
          b=temp
          inc=inc+1
          ; Index
          labels[inc]="Index"
          units[inc]=''
          inc=inc+1
          ; Qflag
          labels[inc]=a.qflag.lablaxis
          units[inc]=a.qflag.units
          inc=inc+1
          ; Position
          for k=0, 1 do begin
             if(k eq 0) then labels[inc]=" geo latitude"
             if(k eq 1) then labels[inc]="geo longitude"
             units[inc]=a.position.units
             inc=inc+1
          endfor
          for k=0, 1 do begin
             if(k eq 0) then labels[inc]=" geo east vel"
             if(k eq 1) then labels[inc]="geo north vel"
             units[inc]=a.vel.units
             inc=inc+1
          endfor
          ;
          farr=fltarr(180)
          in=0
          for l=0,29 do begin
             farr[in]=a.index.dat[0]
             in=in+1
             farr[in]=a.qflag.dat[l,0]
             in=in+1
             for k=0, 1 do begin
                farr[in]= a.position.dat[k,l,0]
                in=in+1
             endfor
             for k=0, 1 do begin
                farr[in]= a.vel.dat[k,l,0]
                in=in+1
             endfor
          endfor
          temp=create_struct('DATREC',farr)
          b=create_struct(b,temp)
          ;
          ; Free Memory
          spdf_delete, temp
          ;
          for j=0L, length-1 do begin
             m=0
             b.epoch=a.epoch.dateph[j]
             for l=0,29 do begin
                b.datrec[m]=a.index.dat[l]
                m=m+1
                b.datrec[m]=a.qflag.dat[l,j]
                m=m+1
                for k=0,1 do begin
                   b.datrec[m]=a.position.dat[k,l,j]
                   m=m+1
                endfor
                for k=0,1 do begin
                   b.datrec[m]=a.vel.dat[k,l,j]
                   m=m+1
                endfor
             endfor   ; end l

             ;Handle JSON file creation for csv=3
             COMMON SHARE, csv2
             if (csv2 EQ 3) AND (j EQ 0) then begin
               datsize = 0
               jdata_array = []
               for jindex1=0, (n_tags(a)-1) DO BEGIN
                 if (ISA(a.(jindex1), /STRING) NE 1) then if (a.(jindex1).var_type NE 'additional_data') then begin
                   if jdata_array EQ !NULL then jdata_array = [jindex1] else jdata_array = [jdata_array, jindex1] ;Variables to include in JSON listing
                 endif
               endfor
               COMMON SHARE3, cjsonstruct
               COMMON SHARE4, nan_count
               datsize = size(jdata_array, /n_elements) ;Number of variables we want to include in JSON listing
               nan_count=0
               for jindex2=0, (datsize-1) DO BEGIN
                 varattsreached = 'false'
                 jtags = tag_names(a.(jindex2))
                 counter = 0

                 ;Check for NaN in data, then change values to ISTP Standard - CWG 07/09/2019
                 if ISA(a.(jindex2).dat, /STRING) NE 1 then begin
                   if (a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] NE !NULL) AND (nan_count EQ 0) then begin
                     nan_count=1      ;this sared variable will force code to add a section in the listng that will inform user that NaNs were changed for JSON
                   endif

                   ; Set a generic NAN replacer value using the case statement then use that replacer value for both
                   ; data replacement (currently done in the case) and fillvalue substitution.
                   ; Ron Yurow (Dec 3, 2021)
                   ;typeCDF = a.(jindex2).cdftype
                   ;CASE typeCDF OF
                   ;  'CDF_REAL4': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_REAL8': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_FLOAT' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_DOUBLE' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_BYTE': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -128
                   ;  'CDF_INT1' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -128
                   ;  'CDF_INT2' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -32768
                   ;  'CDF_INT4' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -2147483648
                   ;  'CDF_INT8' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -9223372036854775808
                   ;  'CDF_UINT1' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 255
                   ;  'CDF_UINT2' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 65535
                   ;  'CDF_UINT4' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 4294967295
                   ;  'CDF_EPOCH' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_EPOCH16' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_TIME_TT2000' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -9223372036854775808
                   ;  'CDF_CHAR' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ; 'CDF_UCHAR' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ;  ELSE : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ;ENDCASE

                   ; NaN replacer
                   nan_fillval_replace = 0

                   typeCDF = a.(jindex2).cdftype
                   CASE typeCDF OF
                     'CDF_REAL4': nan_fillval_replace = -1.0E+31
                     'CDF_REAL8': nan_fillval_replace = -1.0E+31
                     'CDF_FLOAT' : nan_fillval_replace = -1.0E+31
                     'CDF_DOUBLE' : nan_fillval_replace = -1.0E+31
                     'CDF_BYTE': nan_fillval_replace = -128
                     'CDF_INT1' : nan_fillval_replace = -128
                     'CDF_INT2' : nan_fillval_replace = -32768
                     'CDF_INT4' : nan_fillval_replace = -2147483648
                     'CDF_INT8' : nan_fillval_replace = -9223372036854775808
                     'CDF_UINT1' : nan_fillval_replace = 255
                     'CDF_UINT2' : nan_fillval_replace = 65535
                     'CDF_UINT4' : nan_fillval_replace = 4294967295
                     'CDF_EPOCH' : nan_fillval_replace = -1.0E+31
                     'CDF_EPOCH16' : nan_fillval_replace = -1.0E+31
                     'CDF_TIME_TT2000' : nan_fillval_replace = -9223372036854775808
                     'CDF_CHAR' : nan_fillval_replace = " "
                     'CDF_UCHAR' : nan_fillval_replace = " "
                     ELSE : nan_fillval_replace = " "
                   ENDCASE

                   a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = nan_fillval_replace

                 endif

                 for ii=0, (n_tags(a.(jindex2))-1) DO BEGIN
                   if jtags[ii] EQ 'FIELDNAM' then varattsreached = 'true'
                   if varattsreached EQ 'true' then begin
                      ; Check to see if the FILLVAL attribute is not finite.  If it is not, then set it
                      ; to the NaN replacement value.
                      ; Ron Yurow (Dec 3, 2021)
                      IF  jtags[ii] EQ 'FILLVAL' THEN BEGIN
                          IF  ~finite (a.(jindex2).(ii)) THEN a.(jindex2).(ii) = nan_fillval_replace
                      ENDIF

                     if ((a.(jindex2).cdftype EQ 'CDF_EPOCH16') || (a.(jindex2).cdftype EQ 'CDF_EPOCH') || (a.(jindex2).cdftype EQ 'CDF_TIME_TT2000')) then begin ;Convert epochs to iso-8601 for JSON files
                       ;if ((jtags[ii] EQ 'VALIDMIN') || (jtags[ii] EQ 'VALIDMAX') || (jtags[ii] EQ 'FILLVAL') || (jtags[ii] EQ 'DAT')) then begin
                       if ((jtags[ii] EQ 'VALIDMIN') || (jtags[ii] EQ 'VALIDMAX') ||  (jtags[ii] EQ 'DAT')) then begin

    	       ;help,a.(jindex2),/str
    	       ;print,'JENSUN3 ***********'
    	       ;help,jtags[ii]
    	       ;help,a.(jindex2).(ii)
    	       ;print,a.(jindex2).(ii)
    	       ;print,'JENSUN3 ***************'

                         if (TYPENAME(a.(jindex2).(ii)) NE 'STRING') then begin
                           epochIso=cdf_epoch_tojuldays(a.(jindex2).(ii), /string)+'Z'
                         endif else epochIso=a.(jindex2).(ii)+'Z'
                         jvar = create_struct(jtags[ii], epochIso)
                       endif else jvar = create_struct(jtags[ii], a.(jindex2).(ii))
                     endif else jvar = create_struct(jtags[ii], a.(jindex2).(ii))

                     if (counter EQ 0) then begin
                       varstruct = create_struct(jvar)
                      endif else if (jtags[ii] NE 'DATEPH') then begin
                       varstruct = create_struct(varstruct, jvar)
                      endif
                     counter = counter + 1
                   endif
                 endfor
                 jdummystruct = create_struct(a.(jindex2).varname+'_', varstruct)
                 if (jindex2 EQ 0) then cjsonstruct = create_struct(jdummystruct) else cjsonstruct = create_struct(cjsonstruct, jdummystruct)
               endfor
             endif

              ;Handle CSV file creation
              if keyword_set(csv) AND (csv2 NE 3) then begin
                labsize=n_elements(labels)
                for csvindex=0, (labsize-1) DO BEGIN
                   if (j EQ 0) then begin
                      units[0] = 'yyyy-mm-ddThh:mm:ss.sssZ'
                      labunits = labels+'_'+units
                      tagname1 = 'tagg'+STRTRIM(csvindex,2)
                      if (csvindex LE (labsize-2)) then tmpvar1 = STRTRIM(labunits[csvindex],2)+',' else tmpvar1 = STRTRIM(labunits[csvindex],2)
                      tmpstruc1=create_struct(tagname1,tmpvar1)
                      if (csvindex EQ 0) then newlabs=create_struct(tmpstruc1) else newlabs=create_struct(newlabs,tmpstruc1)
                   endif
                   tagname2 = 'tag'+STRTRIM(csvindex,2)
                   if (csvindex LE (labsize-2)) then tmpvar2=STRTRIM(b.(csvindex),2)+',' else tmpvar2=STRTRIM(b.(csvindex),2)
                   tmpstruc2= create_struct(tagname2, tmpvar2)
                   if (csvindex EQ 0) then begin
                      epoch_iso = a.(0).dat[j]
                      epoch_iso=cdf_epoch_tojuldays(epoch_iso, /string)
                      epoch_iso=epoch_iso+'Z,'
                      tmpvar2=STRTRIM(epoch_iso,2)
                      tmpstruc2= create_struct(tagname2, tmpvar2)
                      newb = create_struct(tmpstruc2)
                   endif else begin
                      newb = create_struct(newb, tmpstruc2)
                   endelse
                endfor
                if (j EQ 0) then begin
                   struclength= n_tags(newlabs)
                   newform = '('+strtrim(struclength,2)+'(A))'
                   printf, unit, format=newform,newlabs
                   cc = strlen(epoch_iso)
                   ; Make sure that we don't write a format element 0 times, IDL
                   ; does not like that.
                   ; Ron Yurow (August 10, 2020)
                   ; newform = '(A'+strtrim(cc+1,2)+','+strtrim(struclength-1,2)+'(A))'
                   newform = struclength gt 1 ? '(A'+strtrim(cc+1,2)+','+strtrim(struclength-1,2)+'(A))' : '(A'+strtrim(cc+1,2)+')'
                endif
                printf, unit, format=newform,newb
             endif else if (csv2 NE 3) then begin
                ;Handle .txt files
                if (j EQ 0) then begin
                 printf,unit,format=a.lform,labels
                 printf,unit,format=a.uform,units
                endif
                printf,unit,format=a.dform,b
             endif

          endfor   ; end j
          ;
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             printf, unit, format='(a)',blnk
             printf, unit, text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             status=1
             length=maxrecs
          endif
          ; Free Memory
          spdf_delete, b
      end   ;  end case 4
      ;
      ; Image Data and 3D data (only difference is 3D data will have depend_3)
      ;
      5: begin
          ; Check MAXRECS
          if(n_elements(num_data) eq 0) then num_data=0
          ; Put in appropriate record count
          len=size(a.(0).dat)
          length=len[len[0]+2]
          ; Check for maxrecs begin exceeded
          num_data=length
          num_data=num_data+4
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             printf, unit, text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             printf, unit, format='(a)',blnk
             ; printf, unit, ' '
             status=1
             length=maxrecs
          endif

          status=list_header(a,unit,ntags)

          ;;num=a.(0).fillval
          num=nvar

          final_labels=''
          final_units=''
          final_dep1_values=''
          final_dep2_values=''
          final_dep3_values=''
          atags=tag_names(a)
          inc=0L
          for i=0L, ntags-5 do begin
             if(strlowcase(a.(i).var_type) eq 'data') or ((strlowcase(a.(i).var_type) eq 'support_data') and (a.(i).cdfrecvary ne 'NOVARY')) then begin
                labels=''
                units=''
                dep1_values=''
                dep2_values=''
                dep3_values=''
                st_sz=size(a.(i).dat)
         ;print,'name = ',a.(i).varname
         ;print,'st_sz = ',st_sz
                if(st_sz[0] le 1) then begin
                   ; get labels and units:
                   labels=[labels,label_search(a,st_sz[0],i,0,debug=debug)]
                   ;units=[units,a.(i).units]
                   units=[units,unit_search(a,st_sz[0],i,0)]
                   if(names[i] eq depend0) then begin
                      temp=create_struct(names[i],a.(i).dateph[0])
                   endif else begin
                      temp=create_struct(names[i],a.(i).dat[0])
                   endelse
                   if(inc eq 0) then begin
                      b=temp
                   endif else begin
                      b=create_struct(b,temp)
                   endelse
                   inc=inc+1L
                endif
                if(st_sz[0] eq 2) then begin
                   ; get labels and units:
                   num_var=st_sz[1]
                   for k=0L, num_var-1 do begin
                      labels=[labels,label_search(a,st_sz[0],i,k,debug=debug)]
                      units=[units,unit_search(a,st_sz[0],i,k)]
    	   unique = strtrim(string(inc), 2)
                      temp=create_struct(atags[i]+unique,a.(i).dat[k,0])
                      b=create_struct(b,temp)
                      inc=inc+1
                   endfor
                endif   ; end st_sz(0) eq 2
                ; Free Memory
                spdf_delete, temp
                ;
                labels=labels[1:*]
                final_labels=[final_labels,labels]
         ;help,final_labels
                units=units[1:*]
                final_units=[final_units,units]
                ;
                ; create array of depend_1 values, if they exist, to also be listed
                ; RCJ 07/2013
                ; exist test is done in dependn_search, if does not exist
                ; return ''
                dep1=dependn_search(a,i,1)
                if (dep1[0] ne '') then begin
                   depend1=a.(i).depend_1
                   ; RCJ 05/16/2013  If alt_cdaweb_depend_1 exists, use it instead:
                   q=where(tag_names(a.(i)) eq 'ALT_CDAWEB_DEPEND_1')
                   if (q[0] ne -1) then if (a.(i).alt_cdaweb_depend_1 ne '') then depend1=a.(i).alt_cdaweb_depend_1
                   s=execute('dep1_units=a.'+strtrim(depend1,2)+'.units')
                   dep1=['(@_'+dep1+'_'+dep1_units+')']
                endif
                dep1_values=[dep1_values,dep1]
                ; create array of depend_2 and _3 values, if they exist, to also be listed
                ; RCJ 07/13
                ; exist test is done in dependn_search, if does not exist
                ; return ''
                dep2=dependn_search(a,i,2)
                if (dep2[0] ne '') then begin
                   depend2=a.(i).depend_2
                   ; RCJ 05/16/2013  If alt_cdaweb_depend_2 exists, use it instead:
                   q=where(tag_names(a.(i)) eq 'ALT_CDAWEB_DEPEND_2')
                   if (q[0] ne -1) then if (a.(i).alt_cdaweb_depend_2 ne '') then depend2=a.(i).alt_cdaweb_depend_2
                   s=execute('dep2_units=a.'+strtrim(depend2,2)+'.units')
                   dep2=['(@_'+dep2+'_'+dep2_units+')']
                endif
                dep2_values=[dep2_values,dep2]
                dep3=dependn_search(a,i,3)
                if (dep3[0] ne '') then begin
                   depend3=a.(i).depend_3
                   q=where(tag_names(a.(i)) eq 'ALT_CDAWEB_DEPEND_3')
                   if (q[0] ne -1) then if (a.(i).alt_cdaweb_depend_3 ne '') then depend3=a.(i).alt_cdaweb_depend_3
                   s=execute('dep3_units=a.'+strtrim(depend3,2)+'.units')
                   dep3=['(@_'+dep3+'_'+dep3_units+')']
                endif
                dep3_values=[dep3_values,dep3]
                ;
                ; listing depend_1 values if they exist. RCJ 06/01
                if (n_elements(dep1_values) gt 1) then begin
                   tmp_dep1_values=dep1_values[1:*]
                   while n_elements(dep1_values)-1 le n_elements(labels)-n_elements(tmp_dep1_values) do begin
                      dep1_values=[dep1_values,tmp_dep1_values]
                   endwhile
                   dep1_values=dep1_values[1:*]
                   final_dep1_values=[final_dep1_values,dep1_values]
                endif
                ; listing depend_2 values if they exist. RCJ 06/01
                if (n_elements(dep2_values) gt 1) then begin
                   tmp_dep2_values=dep2_values[1:*]
                   if n_elements(tmp_dep2_values) eq n_elements(labels) then begin
                      ;print,'SAME NUMBER OF ELEMENTS!!!!!!'
                      ; RCJ 07/01 If the initial depend_2 is 2D (now stretched into 1D)
                      ; we don't need to do what goes below:
                   endif else begin
                      k=0
                      dep2_values=''
                      while n_elements(dep2_values)-1 le n_elements(labels)-n_elements(tmp_dep1_values) do begin
                         for kk=0L,n_elements(tmp_dep1_values)-1 do begin
                            dep2_values=[dep2_values,tmp_dep2_values[k]]
                         endfor
                         k=k+1
                         if k ge n_elements(tmp_dep2_values) then k=0
                      endwhile
                   endelse
                   if n_elements(dep2_values) gt 1 then dep2_values=dep2_values[1:*]
                   final_dep2_values=[final_dep2_values,dep2_values]
                endif
                ; listing depend_3 values if they exist.
                if (n_elements(dep3_values) gt 1) then begin
                   tmp_dep3_values=dep3_values[1:*]
                   if n_elements(tmp_dep3_values) eq n_elements(labels) then begin
                      ;print,'SAME NUMBER OF ELEMENTS!!!!!!'
                   endif else begin
                      k=0
                      dep3_values=''
                      while n_elements(dep3_values)-1 le (n_elements(labels)-(n_elements(tmp_dep2_values)*n_elements(tmp_dep1_values))) do begin
                         for kk=0L,(n_elements(tmp_dep2_values)*n_elements(tmp_dep1_values))-1 do begin
                            dep3_values=[dep3_values,tmp_dep3_values[k]]
                         endfor
                         k=k+1
                         if k ge n_elements(tmp_dep3_values) then k=0
                      endwhile
                   endelse
                   if n_elements(dep3_values) gt 1 then dep3_values=dep3_values[1:*]
                   final_dep3_values=[final_dep3_values,dep3_values]
                endif
                ;
                ;
             endif   ; end a.(i).var_type
             ;
          endfor   ; end i
          ;
          final_labels=final_labels[1:*]
          final_units=final_units[1:*]  ;  but cannot printf the units right now
                                        ;  If there are depend_1/_2 they come first.
          ; If there are labels with no corresponding dep1 values,
          ; then add spaces before the first element of the array.
          ; This works as long as the labels which *do not have* corresponding dep1
          ; values come before the labels which *have* corresponding dep1 values.
          ; If that condition is not true, the logic has to be reworked.  RCJ 07/01
          if n_elements(final_dep1_values) gt 1 then begin
             final_dep1_values=final_dep1_values[1:*]
             diff=n_elements(final_labels)-n_elements(final_dep1_values)
             for k=1L,diff do begin
                cmd='space=string("",format="('+strtrim(strlen(final_labels[k])+1,2)+'x,a)")'
                s=execute(cmd)
                final_dep1_values=[space,final_dep1_values]
             endfor
          ;printf,unit,format=a.dpform,final_dep1_values
          endif
          ; same for dep2 values:
          if n_elements(final_dep2_values) gt 1 then begin
             final_dep2_values=final_dep2_values[1:*]
             diff=n_elements(final_labels)-n_elements(final_dep2_values)
             for k=1L,diff do begin
                cmd='space=string("",format="('+strtrim(strlen(final_labels[k])+1,2)+'x,a)")'
                s=execute(cmd)
                final_dep2_values=[space,final_dep2_values]
             endfor
          ;printf,unit,format=a.dpform,final_dep2_values
          endif
          ;
          ; same for dep3 values:
          if n_elements(final_dep3_values) gt 1 then begin
             final_dep3_values=final_dep3_values[1:*]
             diff=n_elements(final_labels)-n_elements(final_dep3_values)
             for k=1L,diff do begin
                cmd='space=string("",format="('+strtrim(strlen(final_labels[k])+1,2)+'x,a)")'
                s=execute(cmd)
                final_dep3_values=[space,final_dep3_values]
             endfor
          endif

         ;help,final_dep1_values,final_dep2_values,final_dep3_values,final_labels
         ;print,'** ',final_dep1_values
         ;print,'** ',final_dep2_values
         ;print,'** ',final_dep3_values
         ;print,'** ',final_labels

          for j=0L, length-1 do begin
             inc=0L
             for i=0L,ntags-5 do begin
                if (strlowcase(a.(i).var_type) eq 'data') or ((strlowcase(a.(i).var_type) eq 'support_data') and (a.(i).cdfrecvary ne 'NOVARY')) then begin
                   ; if(names(i) eq 'EPOCH' or names(i) eq 'EPOCH92') then begin
                   if(names[i] eq depend0) then begin
                      b.(inc)=a.(i).dateph[j]
                      inc=inc+1L
                   endif else begin
                      st_sz=size(a.(i).dat)
                      if(st_sz[0] eq 1) then begin
                         b.(inc)=a.(i).dat[j]
                         inc=inc+1L
                      endif
                      if(st_sz[0] eq 2) then begin
                         num_var=st_sz[1]
                         for k=0L,num_var-1 do begin
                            b.(inc)=a.(i).dat[k,j]
                            inc=inc+1L
                         endfor
                      endif
                   endelse
                endif
             endfor   ; end i

             ;Handle JSON file creation for csv=3
             COMMON SHARE, csv2
             if (csv2 EQ 3) AND (j EQ 0) then begin
               datsize = 0
               jdata_array = []
               for jindex1=0, (n_tags(a)-1) DO BEGIN
                 if (ISA(a.(jindex1), /STRING) NE 1) then if (a.(jindex1).var_type NE 'additional_data') then begin
                   if jdata_array EQ !NULL then jdata_array = [jindex1] else jdata_array = [jdata_array, jindex1] ;Variables to include in JSON listing
                 endif
               endfor
               COMMON SHARE3, cjsonstruct
               COMMON SHARE4, nan_count
               datsize = size(jdata_array, /n_elements) ;Number of variables we want to include in JSON listing
               nan_count=0
               for jindex2=0, (datsize-1) DO BEGIN
                 varattsreached = 'false'
                 jtags = tag_names(a.(jindex2))
                 counter = 0

                 ;Check for NaN in data, then change values to ISTP Standard - CWG 07/09/2019
                 if ISA(a.(jindex2).dat, /STRING) NE 1 then begin
                   if (a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] NE !NULL) AND (nan_count EQ 0) then begin
                     nan_count=1      ;this sared variable will force code to add a section in the listng that will inform user that NaNs were changed for JSON
                   endif

                   ; Set a generic NAN replacer value using the case statement then use that replacer value for both
                   ; data replacement (currently done in the case) and fillvalue substitution.
                   ; Ron Yurow (Dec 3, 2021)
                   ;typeCDF = a.(jindex2).cdftype
                   ;CASE typeCDF OF
                   ;  'CDF_REAL4': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_REAL8': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_FLOAT' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_DOUBLE' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_BYTE': a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -128
                   ;  'CDF_INT1' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -128
                   ;  'CDF_INT2' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -32768
                   ;  'CDF_INT4' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -2147483648
                   ;  'CDF_INT8' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -9223372036854775808
                   ;  'CDF_UINT1' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 255
                   ;  'CDF_UINT2' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 65535
                   ;  'CDF_UINT4' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = 4294967295
                   ;  'CDF_EPOCH' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_EPOCH16' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -1.0E+31
                   ;  'CDF_TIME_TT2000' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = -9223372036854775808
                   ;  'CDF_CHAR' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ; 'CDF_UCHAR' : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ;  ELSE : a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = " "
                   ;ENDCASE

                   ; NaN replacer
                   nan_fillval_replace = 0

                   typeCDF = a.(jindex2).cdftype
                   CASE typeCDF OF
                     'CDF_REAL4': nan_fillval_replace = -1.0E+31
                     'CDF_REAL8': nan_fillval_replace = -1.0E+31
                     'CDF_FLOAT' : nan_fillval_replace = -1.0E+31
                     'CDF_DOUBLE' : nan_fillval_replace = -1.0E+31
                     'CDF_BYTE': nan_fillval_replace = -128
                     'CDF_INT1' : nan_fillval_replace = -128
                     'CDF_INT2' : nan_fillval_replace = -32768
                     'CDF_INT4' : nan_fillval_replace = -2147483648
                     'CDF_INT8' : nan_fillval_replace = -9223372036854775808
                     'CDF_UINT1' : nan_fillval_replace = 255
                     'CDF_UINT2' : nan_fillval_replace = 65535
                     'CDF_UINT4' : nan_fillval_replace = 4294967295
                     'CDF_EPOCH' : nan_fillval_replace = -1.0E+31
                     'CDF_EPOCH16' : nan_fillval_replace = -1.0E+31
                     'CDF_TIME_TT2000' : nan_fillval_replace = -9223372036854775808
                     'CDF_CHAR' : nan_fillval_replace = " "
                     'CDF_UCHAR' : nan_fillval_replace = " "
                     ELSE : nan_fillval_replace = " "
                   ENDCASE

                   a.(jindex2).dat[where(~finite(a.(jindex2).dat), /null)] = nan_fillval_replace

                 endif

                 for ii=0, (n_tags(a.(jindex2))-1) DO BEGIN
                   if jtags[ii] EQ 'FIELDNAM' then varattsreached = 'true'
                   if varattsreached EQ 'true' then begin
                      ; Check to see if the FILLVAL attribute is not finite.  If it is not, then set it
                      ; to the NaN replacement value.
                      ; Ron Yurow (Dec 3, 2021)
                      IF  jtags[ii] EQ 'FILLVAL' THEN BEGIN
                         IF  ~finite (a.(jindex2).(ii)) THEN a.(jindex2).(ii) = nan_fillval_replace
                      ENDIF

                     if ((a.(jindex2).cdftype EQ 'CDF_EPOCH16') || (a.(jindex2).cdftype EQ 'CDF_EPOCH') || (a.(jindex2).cdftype EQ 'CDF_TIME_TT2000')) then begin ;Convert epochs to iso-8601 for JSON files
                       ;if ((jtags[ii] EQ 'VALIDMIN') || (jtags[ii] EQ 'VALIDMAX') || (jtags[ii] EQ 'FILLVAL') || (jtags[ii] EQ 'DAT')) then begin
                       if ((jtags[ii] EQ 'VALIDMIN') || (jtags[ii] EQ 'VALIDMAX') || (jtags[ii] EQ 'DAT')) then begin

    	       ;help,a.(jindex2),/str
    	       ;print,'JENSUN4 ***********'
    	       ;help,jtags[ii]
    	       ;help,a.(jindex2).(ii)
    	       ;print,a.(jindex2).(ii)
    	       ;print,'JENSUN4 ***************'

                         if (TYPENAME(a.(jindex2).(ii)) NE 'STRING') then begin
                           epochIso=cdf_epoch_tojuldays(a.(jindex2).(ii), /string)+'Z'
                         endif else epochIso=a.(jindex2).(ii)+'Z'
                         jvar = create_struct(jtags[ii], epochIso)
                       endif else jvar = create_struct(jtags[ii], a.(jindex2).(ii))
                     endif else jvar = create_struct(jtags[ii], a.(jindex2).(ii))

                     if (counter EQ 0) then begin
                       varstruct = create_struct(jvar)
                      endif else if (jtags[ii] NE 'DATEPH') then begin
                       varstruct = create_struct(varstruct, jvar)
                      endif

                     counter = counter + 1
                   endif
                 endfor
                 jdummystruct = create_struct(a.(jindex2).varname+'_', varstruct)
                 if (jindex2 EQ 0) then cjsonstruct = create_struct(jdummystruct) else cjsonstruct = create_struct(cjsonstruct, jdummystruct)
               endfor
             endif

             ;Handle CSV file creation
             if keyword_set(csv) AND (csv2 NE 3) then begin
                labsize=n_elements(final_labels)
                for csvindex=0, (labsize-1) DO BEGIN
                   if (j EQ 0) then begin
                      final_units[0] = 'yyyy-mm-ddThh:mm:ss.sssZ'
                      dep1_size = n_elements(final_dep1_values)
                      dep2_size = n_elements(final_dep2_values)
                      dep3_size = n_elements(final_dep3_values)
                      if (dep1_size EQ dep2_size && dep2_size EQ dep3_size && dep3_size EQ labsize) then labunits = final_labels+'_'+final_dep1_values+'_'+final_dep2_values+'_'+final_dep3_values+'_'+final_units else labunits = final_labels+'_'+final_units
                      tagname1 = 'tagg'+STRTRIM(csvindex,2)
                      if (csvindex LE (labsize-2)) then tmpvar1 = STRTRIM(labunits[csvindex],2)+',' else tmpvar1 = STRTRIM(labunits[csvindex],2)
                      tmpstruc1=create_struct(tagname1,tmpvar1)
                      if (csvindex EQ 0) then newlabs=create_struct(tmpstruc1) else newlabs=create_struct(newlabs,tmpstruc1)
                   endif
                   tagname2 = 'tag'+STRTRIM(csvindex,2)
                   if (csvindex LE (labsize-2)) then tmpvar2=STRTRIM(b.(csvindex),2)+',' else tmpvar2=STRTRIM(b.(csvindex),2)
                   tmpstruc2= create_struct(tagname2, tmpvar2)
                   if (csvindex EQ 0) then begin
                      epoch_iso = a.(0).dat[j]
                      epoch_iso=cdf_epoch_tojuldays(epoch_iso, /string)
                      epoch_iso=epoch_iso+'Z,'
                      tmpvar2=STRTRIM(epoch_iso,2)
                      tmpstruc2= create_struct(tagname2, tmpvar2)
                      newb = create_struct(tmpstruc2)
                   endif else begin
                      newb = create_struct(newb, tmpstruc2)
                   endelse
                endfor
                if (j EQ 0) then begin
                   struclength= n_tags(newlabs)
                   newform = '('+STRTRIM(struclength,2)+'(A))'
                   printf, unit, format=newform,newlabs
                   cc = strlen(epoch_iso)
                   ; Make sure that we don't write a format element 0 times, IDL
                   ; does not like that.
                   ; Ron Yurow (August 10, 2020)
                   ; newform = '(A'+strtrim(cc,2)+','+strtrim(struclength-1,2)+'(A))'
                   newform = struclength gt 1 ? '(A'+strtrim(cc,2)+','+strtrim(struclength-1,2)+'(A))' : '(A'+strtrim(cc,2)+')'
                endif
                printf, unit, format=newform,newb
             endif else if (csv2 NE 3) then begin
                ;Handle .txt files
                if (j EQ 0) then begin
                  printf,unit,format=a.lform,final_labels
                  q=where (final_dep1_values ne '')
                  if q[0] ne -1 then printf,unit,format=a.dpform,final_dep1_values
                  q=where (final_dep2_values ne '')
                  if q[0] ne -1 then printf,unit,format=a.dpform,final_dep2_values
                  q=where (final_dep3_values ne '')
                  if q[0] ne -1 then printf,unit,format=a.dpform,final_dep3_values
                  printf,unit,format=a.uform,final_units
                endif
                printf,unit,format=a.dform,b
             endif

          endfor   ; end j
          ;
          if(num_data gt maxrecs) then begin
             dif_rec=num_data-maxrecs
             text='# The maximum number of records allowed to be listed is '
             text1='# Your request has exceeded this maximum by '
             printf, unit, format='(a)',blnk
             printf, unit,text,maxrecs
             printf, unit, format='(a,i6)',text1,dif_rec
             status=1
             length=maxrecs
          endif
          ; Free Memory
          spdf_delete, b
      end   ; end case 5
      ;
      ;
      else : begin
             print, 'STATUS= A listing of these data cannot be generated. '
             print, "ERROR=Error: Invalid control variable; convar= ",convar
             close,1
             return, -1
      end
    ndcase   ; end case convar

    eturn, status

    nd

(See external/CDAWlib/LIST_mystruct.pro)

## LIST_MYSTRUCT[6]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:  form_bld.pro

     PURPOSE: Builds format statements

     shft - 0= left justified field; 1= right justified field

    UNCTION form_bld, col_sz, label, units, dat_len, dep_col_sz, depend1_labels, $
      dep2_col_sz, depend2_labels, dep3_col_sz, depend3_labels,form, shft

     Use column size to build label, unit and data format statements

    axlength=max(strlen(depend1_labels)) > max(strlen(depend2_labels))  > max(strlen(depend3_labels)) > strlen(label)
    intab=fix(dep_col_sz-max(strlen(depend1_labels))) < fix(dep2_col_sz-max(strlen(depend2_labels))) < fix(dep3_col_sz-max(strlen(depend3_labels)))<fix(col_sz-strlen(label))

     depend1 and depend2 use the same format (depv) :
     depend1, depend2 and depend3 use the same format (depv) :
    tab=strtrim(mintab,2)
    fld=strtrim(maxlength,2)

    f(shft eq 0) then begin
      if(ltab ne '0') then depv='A'+lfld+','+ltab+'X,1X,' else depv='A'+lfld+',1X,'
    ndif else begin
      if(ltab ne '0') then depv=ltab+'X,A'+lfld+',1X,' else depv='A'+lfld+',1X,'
    ndelse

    f(shft eq 0) then begin
      if(ltab ne '0') then labv='A'+lfld+','+ltab+'X,1X,' else labv='A'+lfld+',1X,'
    ndif else begin
      if(ltab ne '0') then labv=ltab+'X,A'+lfld+',1X,' else labv='A'+lfld+',1X,'
    ndelse

    ol_sz=maxlength > col_sz
    tab=strtrim(fix(col_sz-strlen(units)),2)
    fld=strtrim(strlen(units),2)
    f(shft eq 0) then begin
      if(utab ne '0') then untv='A'+ufld+','+utab+'X,1X,' else untv='A'+ufld+',1X,'
    ndif else begin
      if(utab ne '0') then untv=utab+'X,A'+ufld+',1X,' else untv='A'+ufld+',1X,'
    ndelse

    tab=strtrim(fix(col_sz-dat_len),2)
    f(dtab ne '0') then datv=dtab+'X,'+form+',1X,' $
        else datv=form+',1X,'
    form=create_struct('labv',labv,'untv',untv,'datv',datv,'depv',depv)

    eturn, sform
    nd

(See external/CDAWlib/LIST_mystruct.pro)

## LIST_MYSTRUCT[7]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:  data_len.pro

     PURPOSE: Determines the length of the data field given FORMAT, FILLVAL

    UNCTION data_len,format,fillval,debug=debug

     Set input values if undefined

    tatus=0
    if(n_elements(format) eq 0) then form='null' else form=strmid(format,0,1)
    if(strlen(format) eq 0) then form='null' else begin
     RCJ 11/23/05   It has to be G format or fillvals will be ****
    f(strlen(format) eq 0) then format='G13.6'

     RCJ 18Nov2019 This logic will remove the exponent width part of the format, if present.
                   For example: G10.2E3 -> G10.2
                   According to IDL help, IDL ignores this portion of the format
    ormat1=strmid(format,0,strpos(format,'E',/reverse_search))
    f format1 ne '' then begin
      if keyword_set(DEBUG) then print,'In LIST_mystruct. Changing data format from ',format,' to ',format1
      format=format1
    ndif

    trip=0
    c=0
    ew_form='        '
    var=''
    var=0
    or i=0L, strlen(format)-1 do begin
      ch=strupcase(strmid(format,i,1))
      ; Added format code 'D' Ron Yurow (8 Nov 2016)
      if(ch ne '(') and (ch ne 'A') and (ch ne 'F') and (ch ne 'P') and (ch ne 'D') and $
         (ch ne 'I') and (ch ne 'Z') and (ch ne 'G') and (ch ne 'E') and (ch ne 'B') then begin
         if(ivar eq 0) then nvar=nvar+ch
      endif
      ; Added format code 'D' Ron Yurow (8 Nov 2016)
      if(ch eq 'A') or (ch eq 'F') or (ch eq 'I') or (ch eq 'Z') or (ch eq 'G') or (ch eq 'B') $
         or (ch eq 'E') or (ch eq 'D') then begin
         form=ch
         itrip=1
         ivar=1
      endif
      if(ch eq 'P') then ch=''
      if(ch eq ',') or (ch eq ')') then itrip=0
      if(itrip eq 1) then begin
         strput,new_form,ch,nc
         nc=nc+1
      endif
    ndfor   ; end i
    ormat=strtrim(new_form,2)
    ormlen=strlen(format)-1
    endelse

    ase form of
      'null' : begin
               status=-1
               return, status
      end
      ; RCJ 11/23/05  We are setting formats F,E,G to G13.6 (or wider)
      ;   to accomodate possible fillvals in the data
      'B' : begin
            ; RCJ 04/29/2014.  The value 30 below might have to be adjusted.
            dat_len = 30 > strmid(format,1,formlen)
            dat_len = strmid(dat_len,6,formlen > 4)
      end
      'Z' : begin
            dat_len = 13.6 > strmid(format,1,formlen)
            dat_len = strmid(dat_len,6,formlen > 4)
      end
      'F' : begin
            dat_len = 13.6 > strmid(format,1,formlen)
            ;dat_len = strmid(dat_len,6,4)
     ; RCJ 10/29/2007  Generalizing line above. Same for E and G below.
            dat_len = strmid(dat_len,6,formlen > 4)
      end
      ; Added little used 'D' format type.  Same as 'F' Ron Yurow (8 Nov 2016)
      'D' : begin
            dat_len = 13.6 > strmid(format,1,formlen)
            dat_len = strmid(dat_len,6,formlen > 4)
      end
      'E' : begin
            dat_len = 13.6 > strmid(format,1,formlen)
            ;dat_len = strmid(dat_len,6,4)
            dat_len = strmid(dat_len,6,formlen > 4)
      end
      'G' : begin
            dat_len = 13.6 > strmid(format,1,formlen)
            ;dat_len = strmid(dat_len,6,4)
            dat_len = strmid(dat_len,6,formlen > 4)
      end
      'I' : begin
            ;  Program caused arithmetic error: Floating illegal operand; where?
            if(n_elements(fillval) eq 0) then dat_len=strmid(format,1,formlen) else $
               dat_len=strlen(strtrim(string(fix(fillval)),2)) > strmid(format,1,3)
      end
      'A' : begin
            ;if(n_elements(fillval) eq 0) then dat_len=strmid(format,1,formlen) else $
            ;   dat_len=strlen(strtrim(fillval,2)) > strmid(format,1,3)
            if(n_elements(fillval) eq 0) then dat_len=strmid(format,1,formlen) $
     else begin
        if size(fillval,/tname) eq 'DCOMPLEX' then $
        ; RCJ 11/2006  This is the case of epoch for themis data
               dat_len=strlen(strtrim(real_part(fillval),2)) > strmid(format,1,3) else $
               dat_len=strlen(strtrim(fillval,2)) > strmid(format,1,3)
     endelse
      end
      else : begin
             dat_len=0
      end
    ndcase
     RCJ 11/23/05  It has to be G format or fillvals will be ****:
    f(form eq 'F') or (form eq 'E') then form='G'
    f(nvar ne '') then begin
      format=nvar+form+strtrim(dat_len,2)
      dat_len=fix(nvar)*fix(dat_len)
      nvar=fix(nvar)-1
    ndif else begin
      format=form+strtrim(dat_len,2)
      dat_len=fix(dat_len)
      nvar=0
    ndelse
    rm_st=create_struct('status',status, 'form',format, 'dat_len',dat_len, $
                         'nvar',nvar)
    eturn, frm_st

    nd

(See external/CDAWlib/LIST_mystruct.pro)

## LIST_MYSTRUCT[8]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:  LIST_mystruct.pro

     PURPOSE:  Generates a list output for CDAWweb

     CALLING SEQUENCE:

     FUNCTION LIST_mystruct, a,NOGATT=nogatt,NOVATT=novatt,NORV=norv,$
                             NONRV=nonrv,NO2DRV=no2drv,FILENAME=filename,CSV=csv,$
                             TSTART=TSTART,TSTOP=TSTOP,MAXRECS=maxrecs

     VARIABLES:

     Input:

      a        - an IDL structure

     Keyword Parameters:

      nogatt   - Global attributes output: =0 (print), =1 (no print)
      novatt   - Variable attributes output: =0 (print), =1 (no print)
      norv     - Record varying output: =0 (print), =1 (no print)
      nonrv    - Non record varying output: =0 (print), =1 (no print)
      no2drv   - 2D record varying output: =0 (print), =1 (no print)
      filename - Output filename
      maxrecs  - Maximum record output
      csv      - =0 (regular .txt file), =1 (.csv data+header output), =2 (.csv data and .json header output), =3 (.json data+header output)

     REQUIRED PROCEDURES:

     HISTORY

     Initial version:

             1.0  R. Baldwin  HSTX           2/9/96

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/LIST_mystruct.pro)

## LOGLEVELS (FUNCTION)

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
            LOGLEVELS (function)

     PURPOSE:
            Compute default values for logarithmic axis labeling
            or contour levels. For a range from 1 to 100 these
            would be 1., 2., 5., 10., 20., 50., 100.
            If the range spans more than (usually) 3 decades, only
            decadal values will be returned unless the /FINE keyword
            is set.

     CATEGORY:
            Tools

     CALLING SEQUENCE:
            result = LOGLEVELS([range | MIN=min,MAX=max] [,/FINE]
    [,COARSE=dec])

     INPUTS:
            RANGE -> A 2-element vector with the minimum and maximum
                value to be returned. Only levels _within_ this range
                will be returned. If RANGE contains only one element,
                this is interpreted as MAX and MIN will be assumed as
                3 decades smaller. RANGE superseeds the MIN and MAX
                keywords.

     KEYWORD PARAMETERS:
            MIN, MAX -> alternative way of specifying a RANGE. If only
                one keyword is given, the other one is computed as
                3 decades smaller/larger than the given parameter.
                RANGE superseeds MIN and MAX.

            /FINE -> always return finer levels (1,2,5,...)

            COARSE -> the maximum number of decades for which LOGLEVELS
                shall return fine labels. Default is 3. (non-integer
                values are possible).

     OUTPUTS:
            A vector with "round" logarithmic values within the given
            range.  The result should always contain at least three
            elements (unless COURSE is set to a value less then 0).

     SUBROUTINES:
            none

     REQUIREMENTS:
            none

     NOTES:
            If COARSE is lt 0, the nearest decades will be returned
            instead. The result will always have at least two elements.
            If COARSE forces decades, the result values may be out-of-
            range if RANGE spans less than a decade.

            Caution with type conversion from FLOAT to DOUBLE !!

     EXAMPLE:
            range = [ min(data), max(data) ]
            c_level = LOGLEVELS(range)
            contour,...,c_level=c_level

     MODIFICATION HISTORY:
            Based function of the same name by Martin Schultz

(See external/CDAWlib/loglevels.pro)

## MAKEI

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           MAKEI
     PURPOSE:
           Make a long array with given start and end values and step size.
     CATEGORY:
     CALLING SEQUENCE:
           in = makei(lo, hi, step)
     INPUTS:
           lo, hi = array start and end values.       in
           step = distance beteen values.             in
     KEYWORD PARAMETERS:
     OUTPUTS:
           in = resulting index array.                out
     COMMON BLOCKS:
     NOTES:
           Note: good for subsampling an array.
     MODIFICATION HISTORY:
           Ray Sterner,  14 Dec, 1984.
           Johns Hopkins University Applied Physics Laboratory.
           RES 15 Sep, 1989 --- converted to SUN.

     Copyright (C) 1984, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/makei.pro)

## MAP_KEYWORDS

[Previous Routine] [Next Routine] [List of Routines]

     NAME: MAP_KEYWORDS.PRO

     PURPOSE:  Read in a file of keyword values pairs and assign these to
               IDL keywords

     KEYWORD PARAMETERS:
       ORB_VW    Orbit plot keyword for orbit view up to an array (xy, xz, yz, xr)
       XMIN      Orbit plot keyword for minimum x axis value
       YMIN      Orbit plot keyword for minimum y axis value
       YMAX      Orbit plot keyword for maximum y axis value
       XMAX      Orbit plot keyword for maximum x axis value
       DOYMARK   Orbit plot keyword for interval along the orbit on which the
     	        day of year is plotted
       HRMARK    Orbit plot keyword for interval along the orbit on which the
       		hour of day is plotted
       HRTICK    Orbit plot keyword for tick interval along the orbit
       MNTICK    Minute tick interval
       MNMARK    Minute mark interval
       BZ        Orbit plot keyword for BZ component
       PRESS     Orbit plot keyword for solar wind pressure
       STATION   Mapped plot keyword for an array of stations
       IPROJ     Mapped plot keyword for map projection
     aitoff (15), az. equid. (6), cyl (8), gnom (5), lamb eq area (4)
     merc (9), molle (10), ortho (2), sinsusoidal (14), stero. (1)
       LIM       Mapped plot keyword for map_set limits
       LATDEL    Mapped plot keyword for latitude interval
       LONDEL    Mapped plot keyword for longitude interval
       Ttitle    Mapped plot keyword for title
       SYMSIZ    Mapped plot keyword for symbol size
       LNTHICK   Plot keyword for line thickness.
       SYMCOL    Mapped plot keyword for symbol color
       LNLABEL   Mapped plot keyword for line labels
       CHTSIZE   Character size of text
       REPORT    Flag to write to the REPORT file opened in plotmaster
       PID       Process id
       OUTDIR    This keyword indiates the output directory where a gif file
                 will be placed. If GIF is set but OUTDIR is not, then the gif
                 file will be put in the user's current working directory.
       US        Position of the Sun convention; left U.S.(1); right EUR.-JAP.(0)
                 (Default; US=1)

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occurred.
     AUTHOR:
           Richard Baldwin, HSTX NASA/GSFC Code 632.0, Feb 2, 1997
           baldwin@nssdca.gsfc.nasa.gov    (301)286-7220
     MODIFICATION HISTORY:
           8/30/96 : R. Baldwin   : Add error handling STATUS,DATASET,IMAGE,GIF

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/map_keywords.pro)

## MATCH

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           MATCH
     PURPOSE:
           Routine to match values in two vectors.

     CALLING SEQUENCE:
           match, a, b, suba, subb, [ COUNT =, /SORT ]

     INPUTS:
           a,b - two vectors to match elements, numeric or string datatype

     OUTPUTS:
           suba - subscripts of elements in vector a with a match
                   in vector b
           subb - subscripts of the positions of the elements in
                   vector b with matchs in vector a.

           suba and subb are ordered such that a[suba] equals b[subb]

     OPTIONAL INPUT KEYWORD:
           /SORT - By default, MATCH uses two different algorithm: (1) the
                   /REVERSE_INDICES keyword to HISTOGRAM is used for integer data,
                   while a sorting algorithm is used for non-integer data.   The
                   histogram algorithm is usually faster, except when the input
                   vectors are sparse and contain very large numbers, possibly
                   causing memory problems.   Use the /SORT keyword to always use
                   the sort algorithm.

     OPTIONAL KEYWORD OUTPUT:
           COUNT - set to the number of matches, integer scalar

     SIDE EFFECTS:
           The obsolete system variable !ERR is set to the number of matches;
           however, the use !ERR is deprecated in favor of the COUNT keyword

     RESTRICTIONS:
           The vectors a and b should not have duplicate values within them.
           You can use rem_dup function to remove duplicate values
           in a vector

     EXAMPLE:
           If a = [3,5,7,9,11]   & b = [5,6,7,8,9,10]
           then
                   IDL> match, a, b, suba, subb, COUNT = count

           will give suba = [1,2,3], subb = [0,2,4],  COUNT = 3
           and       suba[a] = subb[b] = [5,7,9]

     METHOD:
           For non-integer data types, the two input vectors are combined and
           sorted and the consecutive equal elements are identified.   For integer
           data types, the /REVERSE_INDICES keyword to HISTOGRAM of each array
           is used to identify where the two arrays have elements in common.
     HISTORY:
           D. Lindler  Mar. 1986.
           Fixed "indgen" call for very large arrays   W. Landsman  Sep 1991
           Added COUNT keyword    W. Landsman   Sep. 1992
           Fixed case where single element array supplied   W. Landsman Aug 95
           Converted to IDL V5.0   W. Landsman   September 1997
           Use a HISTOGRAM algorithm for integer vector inputs for improved
                 performance                W. Landsman         March 2000
           Work again for strings           W. Landsman         April 2000

(See external/CDAWlib/match.pro)

## MLT

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
    	MLT

     PURPOSE:

    	convert UT time to MLT

    	calling sequence:
    	  mt = mlt(year, ut_seconds, mag_long)
    		inputs:  year, time in seconds from Jan. 1 at 00;00:00 UT
    		         magnetic longitude of the observation point

    	        the time in seconds can be found with routine "cnvtime"
    		the magnetic longitude of the obs. point can be found
    		  by using routine "cnvcoord"

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/mlt.pro)

## MONDAY

[Previous Routine] [Next Routine] [List of Routines]

     NAME:  MONDAY.PRO

     PURPOSE:  convert year and day_of_year to month and day or vice versa

     CALLING SEQUENCE:
    	monday,year,doy,mo,day,[/YEARDAY]

    	If the keyword, YEARDAY is set, the routine will take the
    	year, the month, and the day of the year and return the
    	day number of the year (Jan. 1 = 1).

    	If the keyword is not set, the routine will take the
    	year and day of year and return the month and day.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/monday.pro)

## MONTHDAYS

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           MONTHDAYS
     PURPOSE:
           Given a year and month returns number of days in that month.
     CATEGORY:
     CALLING SEQUENCE:
           days = monthdays(yr,mon)
     INPUTS:
           yr = year (like 1988).                     in
           mon = month number (like 11 = Nov).        in
     KEYWORD PARAMETERS:
     OUTPUTS:
           days = number of days in month (like 30).  out
     COMMON BLOCKS:
     NOTES:
           Notes: If mon is 0 then return array of
           month days for entire year.
     MODIFICATION HISTORY:
           R. Sterner,  14 Aug, 1985.
           Johns Hopkins University Applied Physics Laboratory.
           RES 18 Sep, 1989 --- converted to SUN

     Copyright (C) 1985, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/monthdays.pro)

## MOVIE_IMAGES

[Previous Routine] [Next Routine] [List of Routines]

     NAME: MOVIE_IMAGES
     PURPOSE: To plot the image data given in the input parameter astruct
              as a mpeg movie.
     CALLING SEQUENCE:
           out = plotmaster(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
           FRAME     = individual frame to plot
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           LIMIT = if set, limit the number of movie frames allowed -
           this is the default for CDAWEB
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Richard Baldwin, NASA/GSFC/Code 632.0,
     MODIFICATION HISTORY:
          09/30/98 : R. Baldwin   : Initial version

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/movie_images.pro)

## MOVIE_MAP_IMAGES

[Previous Routine] [Next Routine] [List of Routines]

     NAME: MOVIE_MAP_IMAGES
     PURPOSE: To plot a sequence of mapped images into a movie file.

     CALLING SEQUENCE:
           out = movie_map_images(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
        CENTERLONLAT = 2 element array of map center [longitude,latitude]
           FRAME     = individual frame to plot
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image
    	LIMIT = if set, limit the number of movie frames allowed - this is
    		the default for CDAWEB

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Rich Baldwin,  Raytheon STX

           Richard Burley, NASA/GSFC/Code 632.0, Feb 22, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           1/21/98 : R. Baldwin   : Initial version modified from plot_images.pro

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/movie_map_images.pro)

## MOVIE_SKYMAP

[Previous Routine] [Next Routine] [List of Routines]

     NAME: MOVIE_SKYMAP

     PURPOSE: Produce gif/mpeg movie from TWINS images

     CALLING SEQUENCE:
           out = movie_skymap(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure used to produce movie.

     KEYWORD PARAMETERS:
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF      = name of gif file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           COLORBAR = calls function to include colorbar w/ image
           LIMIT = if set, limit the number of movie frames allowed -
           this is the default for CDAWEB

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:

          Tami Kovalick, based on fuv_movie.pro

     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/movie_skymap.pro)

## MOVIE_WIND_MAP

[Previous Routine] [Next Routine] [List of Routines]

     NAME: movie_wind_map
     PURPOSE: To plot a sequence of mapped images into a movie file.
     CALLING SEQUENCE:
           out = movie_wind_map(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           LIMIT     = Limit to the number of frames
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           MGIF      = filename of animated gif output (won't do gif AND mpeg)
           MPEG      = filename of mpeg output (won't do gif AND mpeg)
           CDAWEB    = being run in cdaweb context
           DEBUG    = if set, turns on additional debug output.

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Rita Johnson, 12/2004. Based on movie_map_images.pro
     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/movie_wind_map.pro)

## ORBIT_PLT[1]

[Previous Routine] [Next Routine] [List of Routines]

    unction get_depend0, astrc
    finding the epoch variable by looking at the depend_0 attribute
    instead of just assuming the variable is named "epoch" - TJK 11/26/97
    return the epoch variables tag index value.

    ep0 = tagindex('DEPEND_0',tag_names(astrc.(0)))
    f (dep0[0] ne -1) then begin; found it!
     epoch_var = astrc.(0).(dep0) ; should return the epoch variable name.
     if (epoch_var[0] ne '')then epoch_index = tagindex(epoch_var,tag_names(astrc))
    ndif

    f (n_elements(epoch_index) eq 0) then begin
     epoch_index = tagindex('EPOCH',tag_names(astrc))
    ndif

    eturn, epoch_index
    nd

(See external/CDAWlib/orbit_plt.pro)

## ORBIT_PLT[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: orbax_scl.pro

     PURPOSE: Determines the min and max axis for each axis
              based on defined limits for orbit plots

     xmin     - axis minimum
     xmax     - axis maximum
     rstrc    - Returned structure

    UNCTION orbax_scl, xmin,xmax,valmin,valmax
    print, "xmin=", xmin,xmax
    f(xmin lt 0) then tmax=max([abs(xmin),xmax]) else tmax=xmax
    print, "tmax=",tmax,xmin,xmax
    print, "valmax=",valmin,valmax
     Don't know why this is set but it is screwy; commented out 4/00 RTB
    if(tmax gt 300 and xmin gt -100) then begin
      xmin=-100.0 & xmax=500.0
    endif else begin
     RTB changed 1/27/2000
     RTB changed 3/06/2000

       if(tmax gt 3000.) then begin
      if(tmax gt 1000000.) then begin
       sval = valmax
       if(sval eq 0.) then begin
        print, "STATUS=No VALIDMAX set for the maximum extent of orbit plots"
       endif
      endif

      ; RCJ 01Nov2019  This is the max on more_cdf.c too.
      ;   If this one needs to be increased that one needs to be increased too.
      if(tmax le 1000000.) then sval=1000000.0
      if(tmax le 500000.) then sval=500000.0
      if(tmax le 100000.) then sval=100000.0
      if(tmax le 90000.) then sval=90000.0
      if(tmax le 80000.) then sval=80000.0
      if(tmax le 70000.) then sval=70000.0
      if(tmax le 60000.) then sval=60000.0
      if(tmax le 50000.) then sval=50000.0
      if(tmax le 40000.) then sval=40000.0
      if(tmax le 30000.) then sval=30000.0
      if(tmax le 25000.) then sval=25000.0
      if(tmax le 20000.) then sval=20000.0
      if(tmax le 15000.) then sval=15000.0
      if(tmax le 10000.) then sval=10000.0
      if(tmax le 5000.) then sval=5000.0
      if(tmax le 4000.) then sval=4000.0
      ;  RCJ 01Nov2019  Previously:
      if(tmax le 3000.) then sval=3000.0
      if(tmax le 2000.) then sval=2000.0
      if(tmax le 1500.) then sval=1500.0
      if(tmax le 1000.) then sval=1000.0
      if(tmax le 800.) then sval=800.0
      if(tmax le 500.) then sval=500.0
      if(tmax le 300.) then sval=300.0
      if(tmax le 100.) then sval=100.0
      if(tmax le 40.) then sval=40.0
      if(tmax le 20.) then sval=20.0
      if(tmax le 10.) then sval=10.0
      if(tmax le 5.) then sval=5.0
    xmin=-1.0*sval
    xmax=sval
    endelse  RTB 4/00

    print, "out", xmin,xmax

    strc=create_struct('min',xmin,'max',xmax)

    eturn, rstrc
    nd

(See external/CDAWlib/orbit_plt.pro)

## ORBIT_PLT[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: autoscaler.pro

     PURPOSE: Determines the axis scales for orbit plots

     astrc    -  Input structure
     rstrc    -  Returned structure

    UNCTION autoscaler, astrc, crd_sys=crd_sys

    umstr=astrc.(0)

    xmin=dblarr(numstr)
    ymin=dblarr(numstr)
    zmin=dblarr(numstr)
    xmax=dblarr(numstr)
    ymax=dblarr(numstr)
    zmax=dblarr(numstr)

    s=0
    or i=1L, numstr do begin
      proj='' ;initiate proj or it will be 'NEW' for cases when it shouldn't be. RCJ 08/28/02
      epoch_index = get_depend0(astrc.(i)) ;TJK added 12/4/97
      if (epoch_index lt 0) then begin
         print,'ERROR= No Epoch variable found' & return,-1
      endif
      var_names=tag_names(astrc.(i))

      for j=0L, n_tags(astrc.(i))-1 do begin ; look for the position/orbit variable

         ; also look for whether these variables have been specified as
         ; orbit plotting variables via the display_type attribute.  If so,
         ; handle these slightly differently.

         ;   att_names=tag_names(astrc.(i).(j))
         ;   disp = tagindex('DISPLAY_TYPE',att_names)
         ;   if (disp(0) ne -1) then begin
         ;     c = break_mystring(astrc.(i).(j).(disp(0)),delimiter='>')
         ;     csize = size(c)
         ;     if ((n_elements(c) eq 2) and strupcase(c(0)) eq 'ORBIT') then begin
         ;	proj = 'NEW'
         ;        var_index = j ;variable index in the astrc.(i) structure that
         ;	              ;we want to plot as an orbit plot.
         ;     endif
         ;   endif
         ;TJK commented the above section out since if there are more than one ORBIT
         ;variables in a structure, this will always set var_index to the last variable
         ;in the list, which is obviously not correct...  replaced w/ code below.
         ;10/25/2000   att_names=tag_names(astrc.(i).(j))

         coord = evaluate_orbstruct(astrc.(i).(j))
         if (coord ne ' ') then begin
            if (strupcase(crd_sys) eq strupcase(coord)) then begin
               proj = 'NEW'
               var_index = j
               ;  print, 'In AUTOSCALER, coordinate system selected is ',crd_sys
               ;  print, 'variable being scaled is ',astrc.(i).(j).varname
            endif
         endif
      endfor

      if (proj eq '') then proj=astrc.(i).(0).project ;define project

      ; Double check on structure content and crd_sys
      if (proj eq 'SSC') then begin
         v_temp='XYZ_'+crd_sys
      endif else if (proj eq 'NEW') then begin
         v_temp=var_names[var_index]
      endif else v_temp=crd_sys+'_POS'

      wc=where(var_names eq v_temp, wcn)

      if(wcn gt 0) then begin ; Allow only sub-structures w/ appropriate CRD_SYS
         nel=n_elements(astrc.(i).(epoch_index).dat)
         x=dblarr(nel)
         y=dblarr(nel)
         z=dblarr(nel)

         case proj of
            'SSC': begin
                   w3=execute('dist=astrc.(i).XYZ_'+crd_sys+'.units')
                   ; RCJ 10/06/2004 look for fillval for all 'proj' cases.
    	;     Will use fval just before call to draw_orbit.
                   s=execute('fval= astrc.(i).XYZ_'+crd_sys+'.fillval')
                   if(strupcase(dist) eq "KM") then scale=6371.2 else scale=1.0
                   if(strlen(strtrim(dist,2)) ne 0) then begin
                      w4=execute('x=astrc.(i).XYZ_'+crd_sys+'.dat[0,*]/scale')
                      w5=execute('y=astrc.(i).XYZ_'+crd_sys+'.dat[1,*]/scale')
                      w6=execute('z=astrc.(i).XYZ_'+crd_sys+'.dat[2,*]/scale')
                      ; RTB testing 3/16/2000
                      w6=execute('valmin=astrc.(i).XYZ_'+crd_sys+'.validmin/scale')
                      w6=execute('valmax=astrc.(i).XYZ_'+crd_sys+'.validmax/scale')

                      if(not w3) or (not w4) or (not w5) or (not w6) then begin
                         print, " Error in the execute command for ssc variable "
                         return, -1
                      endif
                   endif
                   end
            'NEW': begin ; new way - defined by the display_type attribute
                   w3=execute('dist=astrc.(i).(var_index).units')
                   s=execute('fval= astrc.(i).(var_index).fillval')
                   if(strupcase(dist) eq "KM") then scale=6371.2 else scale=1.0
                   if(strlen(strtrim(dist,2)) ne 0) then begin
                      w4=execute('x=astrc.(i).(var_index).dat[0,*]/scale')
                      w5=execute('y=astrc.(i).(var_index).dat[1,*]/scale')
                      w6=execute('z=astrc.(i).(var_index).dat[2,*]/scale')
                      ; RTB testing 3/16/2000
                      w6=execute('valmin=astrc.(i).(var_index).validmin/scale')
                      w6=execute('valmax=astrc.(i).(var_index).validmax/scale')

                      if(not w3) or (not w4) or (not w5) or (not w6) then begin
                         print, " Error in the execute command for NEW cdaw variable "
                         return, -1
                      endif
                   endif
                   end
            else: begin ; original cdaweb case
                  w3=execute('dist=astrc.(i).'+crd_sys+'_pos.units')
                  s=execute('fval= astrc.(i).'+crd_sys+'.fillval')
                  if(strupcase(dist) eq "KM") then scale=6371.2 else scale=1.0
                  if(strlen(strtrim(dist,2)) ne 0) then begin
                     w4=execute('x=astrc.(i).'+crd_sys+'_pos.dat[0,*]/scale')
                     w5=execute('y=astrc.(i).'+crd_sys+'_pos.dat[1,*]/scale')
                     w6=execute('z=astrc.(i).'+crd_sys+'_pos.dat[2,*]/scale')
                     ; RTB testing 3/16/2000
                     w6=execute('valmin=astrc.(i).'+crd_sys+'_pos.validmin/scale')
                     w6=execute('valmax=astrc.(i).'+crd_sys+'_pos.validmax/scale')

                     if(not w3) or (not w4) or (not w5) or (not w6) then begin
                        print, " Error in the execute command for cdaw variable "
                        return, -1
                     endif
                  endif
                  end
         endcase

         axmin[ns]=min(x,max=maxmax)
         axmax[ns]=maxmax
         aymin[ns]=min(y,max=maymax)
         aymax[ns]=maymax
         azmin[ns]=min(z,max=mazmax)
         azmax[ns]=mazmax

         ns=ns+1
      endif ; end crd_sys structure test
    ndfor

    xmin=min(axmin)
    ymin=min(aymin)
    zmin=min(azmin)
    xmax=max(axmax)
    ymax=max(aymax)
    zmax=max(azmax)

     Test code rtb 3/08/99
    help, /struct, astrc
    print, valmin
    print, valmax

    size=size(valmin)
    f(vsize[0] eq 0) then begin
     xstr=orbax_scl(fxmin,fxmax,valmin,valmax)
     ystr=orbax_scl(fymin,fymax,valmin,valmax)
     zstr=orbax_scl(fzmin,fzmax,valmin,valmax)
    ndif else begin
     xstr=orbax_scl(fxmin,fxmax,valmin[0],valmax[0])
     ystr=orbax_scl(fymin,fymax,valmin[0],valmax[0])
     zstr=orbax_scl(fzmin,fzmax,valmin[0],valmax[0])
    ndelse

    strc=create_struct('xmin',xstr.min,'xmax',xstr.max,'ymin',ystr.min,'ymax',ystr.max,'zmin',zstr.min,'zmax',zstr.max)

    eturn, rstrc
    nd

(See external/CDAWlib/orbit_plt.pro)

## ORB_MGR

[Previous Routine] [Next Routine] [List of Routines]

     NAME: rmvar_strc.pro

     PURPOSE: Removes indicated variable from the structure if present

     astrc    -  Input structure
     vname    -  Variable name

    UNCTION rmvar_strc, astrc, vname

    amest=tag_names(astrc)
    s_tags=n_tags(astrc)

    for k=0, ns_tags-1 do begin

     if(namest[k] ne vname) then begin
      if(k eq 0) then b=create_struct(namest[k],astrc.(k)) else begin
        temp=create_struct(namest[k],astrc.(k))
        b=create_struct(b,temp)
      endelse
     endif
    endfor

    eturn, b
    nd

    +
     NAME: orb_handle.pro

     PURPOSE: Converts handles to data for a given structure

     a    -  Input structure
     b    -  Output structure

    UNCTION orb_handle, a

    namest=tag_names(a)
    ns_tags=n_tags(a)

    for k=0, ns_tags-1 do begin
      names=tag_names(a.(k))
      ntags=n_tags(a.(k))
      whc=where(names eq 'HANDLE',whn)
       if(whn) then begin
        handle_value, a.(k).HANDLE, dat
        if(n_elements(dat) gt 1) then dat=reform(dat)
        temp=create_struct('DAT',dat)
        temp1=create_struct(a.(k),temp)
        temp2=create_struct(namest[k],temp1)
        if(k eq 0) then b=temp2 else b=create_struct(b,temp2)
       endif else begin
        temp2=create_struct(namest[k],a.(k))
        if(k eq 0) then b=temp2 else b=create_struct(b,temp2)
       endelse

    endfor
    =0 ; free structure a
    eturn, b
    nd

    UNCTION evaluate_orbstruct, a
     determine if there's an display_type attribute for this structure
     and if so, whether it is defined as "orbit" or not.  If so, whether
     the coordinate system is defined, ie. orbit>coord=gse

     Verify that the input variable is a structure
     = size(a)
    f (b[n_elements(b)-2] ne 8) then begin
     print,'ERROR=Input parameter is not a valid structure.' & return,-1
    ndif

    tags = tag_names(a) ; get names of all attributes for structure

     Attempt to determine the coordinate system based on the display_type
     attribute values.

     = tagindex('DISPLAY_TYPE',atags)
    f (b[0] ne -1) then begin
     c = break_mystring(a.(b[0]),delimiter='>')
     csize = size(c)
     if (csize[1] eq 2)then begin
       d = break_mystring(c[1], delimiter='=')
       dsize = size(d)
       if (dsize[1] eq 2) then begin
         if (strupcase(d[0]) eq 'COORD') then coord = strupcase(d[1])
       endif
     endif
    ndif

    f (n_elements(coord) eq 0) then coord = ' '

    eturn, coord
    nd

(See external/CDAWlib/orb_mgr.pro)

## OVERLAY[1]

[Previous Routine] [Next Routine] [List of Routines]

      checks for gaps in the data and replace them with NAN

(See external/CDAWlib/overlay.pro)

## OVERLAY[2]

[Previous Routine] [Next Routine] [List of Routines]

    $Author: nikos $
    $Date: 2022-09-23 18:16:23 -0700 (Fri, 23 Sep 2022) $
    $Header: /home/cdaweb/dev/control/RCS/overlay.pro,v 1.4 2017/01/23 20:31:35 rchimiak Exp tkovalic $
    $Locker: tkovalic $
    $Revision: 31135 $
    +------------------------------------------------------------------------
     Description:
        graph an element of a set of time series plots on a single panel

     Params:
        i = order of the elment being plotted

        iter_per_panel = number of elements that will be plotted on
                         that panel
        mytimes = the abscissa values to be plotted

        mydata = the ordinate data to be plotted

        psize = panel hekght

     Keywords:
        YUNIT
           Y axis left label

        YTITLE
           Y axis right label

        XRANGE
           min and max abscissa values to be plotted

        YRANGE
           min and max values to be plotted

        YLOG
           specifies logarithmic or linear Y axis

        POSITION
           4-element vector giving the lower left and upper right corners
              of the panel

        NOGAPS
           if set, gaps in the data will be ignored

        NOERASE
           specifies that the previous plot is not to be erased when running
              the plot procedure.

        _EXTRA
           allows properties inheritance from one graphic to be used for other graphics.

        YTICK_GET
           return the values of the tick marks for the y axis

        COLOR
           designated color for that element

     Output:
           out = status flag, 0=0k, -1 = problem occured.

(See external/CDAWlib/overlay.pro)

## PACK

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           PACK
     PURPOSE:
           Compress an un- compressed image
     CATEGORY:

     CALLING SEQUENCE:
           CompressedImage = UNPACK(UncompressedImage)
     INPUTS:
           Image
     KEYWORD PARAMETERS:
           None
     OUTPUTS:
           An uncompressed image
     COMMON BLOCKS:
           COMPRESSION_TABLES
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## PLASMA_MOVIE

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLASMA_MOVIE
     PURPOSE: To plot plasmagram image data given in the input parameter astruct
              as a mpeg movie.
     CALLING SEQUENCE:
           out = plasma_movie(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the image variable in the structure to plot

     KEYWORD PARAMETERS:
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Richard Baldwin, NASA/GSFC/Code 632.0,
     MODIFICATION HISTORY:
          09/30/98 : R. Baldwin   : Initial version

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plasma_movie.pro)

## PLOTMASTER

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOTMASTER
     PURPOSE: To plot the data given in 1 to 10 anonymous structure of the type
              returned by the read_mycdf function.  This function determines
              the plot type for each variable, and generates the plot.
     CALLING SEQUENCE:
           out = plotmaster(a,[more_structures])
     INPUTS:
           a = structure returned by the read_mycdf procedure.

     KEYWORD PARAMETERS:
       TSTART =  String of the form '1996/01/02 12:00:00' or a DOUBLE CDF_EPOCH
       time that is the desired start time of the plots. Data is clipped or
       padded to conform to this time. Default is the start time of the
       earliest data.

       TSTOP = String of the form '1996/01/02 12:00:00' or a DOUBLE
       CDF_EPOCH time that is the desired stop time of the plots. Data is
       clipped or padded to conform to this time. Default is the stop time of
       the latest data.

       GIF
        Set to send plot(s) to a gif file, ie. /GIF or GIF=1L. If set a file
        will be produced in the current working directory (see OUTDIR keyword),
        using the following naming conventions: Spacecraft_instrument_pid_# (see
        the PID keyword for customization). If GIF is not set then the plot(s)
        will be put into an x-window.

        PS
          Set to send plot to a ps file. Works just as GIF above.

        PID
        May be used to customize part of the name of a gif file. The value of
        PID may be either a number or a string and will be inserted in the gif
        file name as follows: Spacecraft_instrument_pid_#.gif. If GIF is not
        set then the plot(s) will be put into an x-window and this keyword is
        ignored.

        OUTDIR
        This keyword indiates the output directory where a gif file will be
        placed. If GIF is set but OUTDIR is not, then the gif file will be put
        in the user's current working directory.GIF

        AUTO
        Set this keyword to use autoscaling instead of the variables SCALEMIN
        and SCALEMAX attribute values. The scales will be set to the min and
        max values of the data, after fill values have been filtered from the
        data (see also NONOISE keyword). If the user wishes to modify variable
        scale values for plotting purposes, you may do so by changing the
        appropriate data structure values, ie. struct.variable.scalemin = 0.0.
        Please use great care in modifying the data structures values since
        they will greatly influence what your plots or listings may look like.

        CDAWEB
        Set this keyword to force the margin on the right side of time series
        plots to be 100 pixels. This is the same margin used for spectrograms
        for the color bar. By default, PLOTMASTER will examine the data, and if
        ANY spectrograms will be produced, then it will align the margins
        properly. This keyword is only necessary for use in the CDAWeb system.

        SLOW
        Set this keyword to have spectrogram plotted using the POLYFILL method.
        This method is slower but more accurate than TV (used in the QUICK method).

        SMOOTH
        Set this keyword to have spectrogram data reduced prior to plotting.
        This will increase plotting speed significantly.

        QUICK
        Set this keyword to have spectrograms plotted using the TV method.
        This method is very fast, but will produce inaccurate spectrograms
        if scales are non-linear or if fill data or data gaps are present
        in the data.

        THUMBSIZE
        Set this to change the "thumbnail" size of each image when plotting
        a series of images. The default is 50w x 62h. 12 pixels is added to
        the height to allow for the time stamps under each image. So, if
        you specify a thumsize of 70 pixels, each will actually be 70x82.

        FRAME
        Used to indicate the frame number within a series of images. If you
        specify FRAME = 2, then plotmaster will produce a "full size" version
        of the 3rd image in a sequence of images.

           COMBINE  = if set, all time series and spectrogram plots will be
                      combined into a single window or gif file.
           NONOISE  = if set, filter values outside 3-sigma from the mean
           DEBUG    = if set, turns on additional debug output.
           ELEMENTS = if set, then only these elements of a dimensional variable
                      will be plotted for stack_plot use only (right now).

       LIMIT_MOVIE = if set, then the number of frames in a movie file
       will be limited by the underlying s/w routines (to 200 or so as of
       2/2006)       if not set, no limit on the # of frames (TJK 2/9/2006)

       TOP_TITLE - if set, adjust the top margin a bit to allow a total
                   of 3 lines of title.  The value of top_title allows a
                   user to pass in an additional line of text, which
                   cdaweb is using for the binning labels.

      PLOTMERGE
        Set this keyword to plot multiple time series data on the same panel.
        PLOTMERGE = 'vector' will plot together vector components (i.e. Bx, By, Bz)
        emanating from a single variable.
        PLOTMERGE = 'mission' will plot together identical variables from
        cluster missions (i.e., MMS)

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occurred.
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 22, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           8/13/96 : R. Burley    : Add NONOISE keyword
           8/30/96 : R. Baldwin   : Add error handling STATUS,DATASET,IMAGE,GIF
           8/30/96 : R. Baldwin   : Add orbit plotting
    	1/7/97  ; T. Kovalick  : Modified many of the code that goes w/ the
    				 keywords; GIF, CDAWEB, TSTART,	TSTOP and added
    				 the header documentation for them. Still more
    				 work to do...
           2/10/97 ; R. Baldwin   : Add SSCWEB keyword and map_keywords.pro
    				 function
    	6/6/97  ; T. Kovalick  : Added the Stacked time series plot type.

    	9/4/97	; T. Kovalick  : Added the ELEMENTS keyword for stack_plot
    				 usage, it could also be used in time_series.
            4/98   ; R. Baldwin   : Added virtual variable plot types;
    				 plot_map_images.pro
           11/98   ; R. Baldwin   : Added movie_images and movie_map_images

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration. All Rights Reserved.

(See external/CDAWlib/plotmaster.pro)

## PLOT_FLUXIMAGES

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_FLUXIMAGES
     PURPOSE: To plot the image data given in the input parameter astruct.
              Can plot as "thumbnails" or single frames.

     CALLING SEQUENCE:
           out = plot_fluximages(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
           THUMBSIZE = size (pixels) of thumbnails, default = 140 (i.e. 140x140) - due to restrictions
    			in the underlying code.
           FRAME     = individual frame to plot
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
    	Tami Kovalick, Raytheon ITSS, July 25, 2000 - this program is based on the plot_images
    	program originally written by R. Burley.  It is being modified for use w/ Rick's new
    	plot_enaflux5 plotting code.

     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_fluximages.pro)

## PLOT_FUV_IMAGES[1]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: GRID_MAP
     PURPOSE: To overlay a map grid on top of an image
     CALLING SEQUENCE:
            out = grid_map( )
     INPUTS:

     KEYWORD PARAMETERS:

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Rich Baldwin,  Raytheon STX
     MODIFIED: june 17, 2011 - TJK replaced all occurrences of
                               !d.n_colors w/ !d.table_size

(See external/CDAWlib/plot_fuv_images.pro)

## PLOT_FUV_IMAGES[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_FUV_IMAGES
     PURPOSE: To plot FUV image data given in the input parameter astruct.
              Can plot as "thumbnails" or single frames.
     CALLING SEQUENCE:
           out = plot_FUV_images(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
        CENTERLATLON = 2 element array of map center [latitude,longitude]
           FRAME     = individual frame to plot
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           PNG      = name of png file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image
    	MOVIE = If this routine is being called to produce an mpeg then
    		we don't want the 'frame' number in the output filename.
    		This keyword takes care of that.
     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.

     MODIFICATION HISTORY:
          12/08/00 : R. Burley    : Collaborated with H.Frey of UCB to process for
                                    IMAGE/FUV instrument.  Renamed plot_fuv_images
                                    to avoid conflict with original plot_map_images.
          10/11/01 : RCJ : Made it work with CDAWeb s/w.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_fuv_images.pro)

## PLOT_IMAGES

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_IMAGES
     PURPOSE: To plot the image data given in the input parameter astruct.
              Can plot as "thumbnails" or single frames.
     CALLING SEQUENCE:
           out = plotmaster(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
           THUMBSIZE = size (pixels) of thumbnails, default = 40 (i.e. 40x40)
           FRAME     = individual frame to plot
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 22, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           8/13/96 : R. Burley    : Add and utilize TSTART, TSTOP and NONOISE
                                  : keywords.  Add frame times to displays.
           8/18/96 : R. Burley    : If no data in requested time span then
                                  : output appropriate message to window/gif.
           8/19/96 : R. Burley    : Output warning message if all data points
                                  : are outsize validmin/max values.
          10/30/96 : R. Baldwin   : Added colobar function
          6/17/2011 : T Kovalick  : replace !d.n_colors w/ !d.table size

(See external/CDAWlib/plot_images.pro)

## PLOT_MAPS

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_MAPS
     PURPOSE: To plot the geographic maps in various map projections.

     CALLING SEQUENCE:
           out = plot_maps(a,vlat=vlat,iproj=iproj,limit=limit,$
              latdel=latdel,londel=londel,Ttitle=thetitle,$
              pmode=pmode,rng_val=rng_val,num_int=num_int,$
              ptype=ptype,lthik=lthik,symsiz=symsiz,symcol=symcol,$
              charsize=charsize,xmargin=xmargin,ymargin=ymargin,$
              xoffset=xoffset,yoffset=yoffset,lnlabel=lnlabel,$
              _extra=extras)
     INPUTS:
           a = structure returned by the read_mycdf procedure.
     projections:
     aitoff (15), az. equid. (6), cyl (8), gnom (5), lamb eq area (4)
     merc (9), molle (10), ortho (2), sinsusoidal (14), stero. (1)

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_maps.pro)

## PLOT_MAP_IMAGES[1]

[Previous Routine] [Next Routine] [List of Routines]

     Procedure Name:       lltodr
           Author:  J. M. O'Meara
     Purpose:  Convert latitude/longitude to  3-D position vector

     INPUTS:
       lat                   Latitude of the point on the earth
       lon                   Longitude of the point on the earth
       r                     Radius scalar

     Outputs:
                   x,y,z                 3-D position vector

(See external/CDAWlib/plot_map_images.pro)

## PLOT_MAP_IMAGES[2]

[Previous Routine] [Next Routine] [List of Routines]

     PROGRAM NAME:  lltopix
     Purpose:  Calculate the row,col pixel locations of a point, given
               the latitude and longitude of the point on the earth
               and the spacecraft's orbit and attitude

     INPUTS:
              lat           Latitude of the point on the earth
              lon           Longitude of the point on the earth
              emis_hgt      Radiation emission height (km)
              xax           X axis: direction of l0
              yax           Y axis: zax X xax
              zax           Z axis: direction in plane of xax and att perp to xax
              orb           GCI orbital postion (km)
              epoch         CDF time

     OUTPUTS:
              row           Pixel row location
              col           Pixel column location
              angle         Angle between Lpix and pos

     PROGRAM CALLS:
              geigeo
     AUTHOR:
           Rich Baldwin,  Raytheon STX

(See external/CDAWlib/plot_map_images.pro)

## PLOT_MAP_IMAGES[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: GRID_MAP
     PURPOSE: To overlay a map grid on top of an image
     CALLING SEQUENCE:
            out = grid_map( )
     INPUTS:

     KEYWORD PARAMETERS:

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Rich Baldwin,  Raytheon STX

(See external/CDAWlib/plot_map_images.pro)

## PLOT_MAP_IMAGES[3]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: GRID_UVI
     PURPOSE: To overlay a map grid on top of image polar uvi images
     CALLING SEQUENCE:
            out = grid_uvi( )
     INPUTS:

     KEYWORD PARAMETERS:

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Rich Baldwin,  Raytheon STX

(See external/CDAWlib/plot_map_images.pro)

## PLOT_MAP_IMAGES[4]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_MAP_IMAGES
     PURPOSE: To plot the map image data given in the input parameter astruct.
              Can plot as "thumbnails" or single frames.
     CALLING SEQUENCE:
           out = plot_map_images(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
        CENTERLONLAT = 2 element array of map center [longitude, latitude]
           THUMBSIZE = size (pixels) of thumbnails, default = 40 (i.e. 40x40)
           FRAME     = individual frame to plot
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           PNG      = name of png file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first
           frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Rich Baldwin,  Raytheon STX

           Richard Burley, NASA/GSFC/Code 632.0, Feb 22, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           1/21/98 : R. Baldwin   : Initial version modified from plot_images.pro

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_map_images.pro)

## PLOT_OVER[1]

[Previous Routine] [Next Routine] [List of Routines]

      Generates y-axis labels for time series plots with the plotmerge option

(See external/CDAWlib/plot_over.pro)

## PLOT_OVER[2]

[Previous Routine] [Next Routine] [List of Routines]

    $Author: nikos $
    $Date: 2022-09-23 18:16:23 -0700 (Fri, 23 Sep 2022) $
    $Header: /home/cdaweb/dev/control/RCS/plot_over.pro,v 1.48 2018/05/07 18:45:33 johnson Exp tkovalic $
    $Locker: tkovalic $
    $Revision: 31135 $
    +------------------------------------------------------------------------
     Description:
        To generate a time series plot that overlay the components on one plot.

     Params:
        Xvar = structure containing the Epoch variable structure of the
                     type returned by the read_mycdf structure.
        Yvar = structure containing the variable to be plotted against
                     the Epoch variable in the Xvar parameter

     Keywords:
        TSTART
           Forces the time axis to begin at this Epoch time

        TSTOP
           Forces the time axis to end at this Epoch time

        ELEMENTS
            if set, then only these elements of a dimensional variable
                      will be plotted.

        POSITION
           If set, this routine will draw the plot(s) at this position
                      of an existing window, rather than open a new one
        FIRSTPLOT
           Use this key in conjunction with the position keyword. Set
                      this flag to indicate that the variable is the first in the
                      window

        LASTPLOT
           Use this key in conjunction with the position keyword. Set
                      this flag to indicate that the variable is the last in the
                      window

        PANEL_HEIGHT
           vertical height, in pixels, of each panel

        CDAWEB
           If set, the plot will have sufficient margin along the Z
              axis to hold a colorbar

        GIF
           If set, the plot will be a .gif file instead of Xwindow

        PNG
           If set, the plot will be a .png file instead of Xwindow

        XSIZE
           if set, forces the plot window to this width

        YSIZE
           if set, forces the plot window to this height

        AUTO
           if set, turns auto-scaling on

        NOGAPS
           if set, eliminates data gap scanning

        NONOISE
           if set, filter out values outside 3 sigma from mean

        IGNORE_DISPLAY_TYPE
           if set, causes the attribute display_type to be ignored

        NOSUBTITLE
           if set, will not print 'time range = ' subtitle even after
              the last graph. Needed for timetext case

        ONLYLABEL
           if set, graph position is calculated but graph is not
              plotted. However, the x-axis label *is* plotted.
              Utilized by timetext case

        SCATTER
           if set, display a scatter plot (each point is plotted as a
              dot, no lines connect the dots

        COMBINE
           if set, need to add the dataset name to the y axis label

        DEBUG
           if set, turns on additional debug output.

        PLOTMERGE
           if set to 1 will combine the x,y,z vector components on one plot
              if set to 2 will combine different datasets with commonality into one
                plot

     Output:
           out = status flag, 0=0k, -1 = problem occured.

(See external/CDAWlib/plot_over.pro)

## PLOT_PLASMAGRAM

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_PLASMAGRAM
     PURPOSE: To plot the image as a plasmagram given the data structure
    	   as returned from read_myCDF.pro
              Can plot as "thumbnails" or single frames.
     CALLING SEQUENCE:
           out = plotmaster(astruct,zname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
    	zname = name of z variable to plot as a plasmagram.

     KEYWORD PARAMETERS:
           THUMBSIZE = size (pixels) of thumbnails, default = 50 (i.e. 50x50)
           FRAME     = individual frame to plot
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           PNG      = name of png file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image
    	MOVIE = if set, don't override the filename specified in the GIF
    		keyword.
           TOP_TITLE = if set, use this title for the window

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
    	Tami Kovalick, RSTX, March 3, 1998
    	Based on plot_images.pro
     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_plasmagram.pro)

## PLOT_SKYMAP

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_SKYMAP
     PURPOSE: To plot the image data with the TWINS project provided
              skymap software.

              Can plot as "thumbnails" or single frames.

     CALLING SEQUENCE:
           out = plotmaster(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
           THUMBSIZE = size (pixels) of thumbnails, default = 40 (i.e. 40x40)
           FRAME     = individual frame to plot
           XSIZE     = x size of single frame
           YSIZE     = y size of single frame
           GIF       = name of gif file to send output to
           PNG      = name of png file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin imaging, default = first frame
           TSTOP     = time of frame to stop imaging, default = last frame
           NONOISE   = eliminate points outside 3sigma from the mean
           CDAWEB    = being run in cdaweb context, extra report is generated
           DEBUG    = if set, turns on additional debug output.
           COLORBAR = calls function to include colorbar w/ image
           MOVIE = If this routine is being called to produce an mpeg
           then we don't want the 'frame' number in the output
           filename. This keyword takes care of that.

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Tami Kovalick October, 2009

     MODIFICATION HISTORY: Held in RCS

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_skymap.pro)

## PLOT_SPECTROGRAM

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_SPECTROGRAM
     PURPOSE: To generate a spectrogram plot given the anonymous structures
              returned by the read_mycdf function.
     CALLING SEQUENCE:
           out = plot_spectrogram(Xstruct,Ystruct,Zstruct)
     INPUTS:
           Xstruct = structure containing the Epoch variable structure of the
                     type returned by the read_mycdf structure.
           Ystruct = structure containing the variable to be plotted against
                     the Epoch variable in the Xstruct parameter
           Zstruct = structure containing the variable to be plotted as Z.
     KEYWORD PARAMETERS:
    	TSTART   = Forces the time axis to begin at this Epoch time.
    	TSTOP    = Forces the time axis to end at this Epoch time.
    	ELEMENTS = if set, then only these elements of a dimensional variable
                      will be plotted.
    	POSITION = If set, this routine will draw the plot(s) at this position
                      of an existing window, rather than open a new one.
           FIRSTPLOT= Use this key in conjunction with the position keyword. Set
                      this flag to indicate that the variable is the first in the
                      window.
           LASTPLOT = Use this key in conjunction with the position keyword. Set
                      this flag to indicate that the variable is the last in the
                      window.
           PANEL_HEIGHT = vertical height, in pixels, of each panel
    	CDAWEB   = If set, the plot will have sufficient margin along the Z
                      axis to hold a colorbar.
           GIF      = If set, the plot will be a .gif file instead of Xwindow
           PNG     = if set, the plot will be a .png file instead of Xwindow
    	XSIZE    = if set, forces the plot window to this width
           YSIZE    = if set, forces the plot window to this height
    	AUTO     = if set, turns auto-scaling on
           NOGAPS   = if set, eliminates data gap scanning
           NOCLIP   = set when writing to GIF or PNG file
           IGNORE_DISPLAY_TYPE = if set, causes the attribute display_type to
    			      be ignored.
    	NOSUBTITLE = if set, will not print 'time range = ' subtitle even after
    			the last graph. Needed for timetext case. RCJ
    	COMBINE = if set, need to add the dataset name to the y axis label
    		  added 10/22/2003 - TJK.
           DEBUG    = if set, turns on additional debug output.
     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 22, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           8/20/96  R. Burley      : Reform the epoch data if retrieved from
                                   : a handle to remove spurious extra dim.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_spectrogram.pro)

## PLOT_STACK

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_STACK
     PURPOSE: To generate a multiple line time series plot given the
    	   anonymous structures returned by the read_mycdf function.
     CALLING SEQUENCE:
           out = plot_stack(Xstruct,Ystruct)
     INPUTS:
           Xstruct = structure containing the Epoch variable structure of the
                     type returned by the read_mycdf structure.
           Ystruct = structure containing the variable to be plotted against
                     the Epoch variable in the Xstruct parameter
    	Zstruct = structure containing the variable to be used as the color
    		  bar for scaling and labeling purposes.
     KEYWORD PARAMETERS:
           TSTART   = Forces the time axis to begin at this Epoch time.
           TSTOP    = Forces the time axis to end at this Epoch time.
           ELEMENTS = if set, then only these elements of a dimensional variable
                      will be plotted.
           POSITION = If set, this routine will draw the plot(s) at this position
                      of an existing window, rather than open a new one.
           FIRSTPLOT= Use this key in conjunction with the position keyword. Set
                      this flag to indicate that the variable is the first in the
                      window.
           LASTPLOT = Use this key in conjunction with the position keyword. Set
                      this flag to indicate that the variable is the last in the
                      window.
           PANEL_HEIGHT = vertical height, in pixels, of each panel
           CDAWEB   = If set, the plot will have sufficient margin along the Z
                      axis to hold a colorbar.
           GIF      = If set, the plot will be a .gif file instead of Xwindow
           XSIZE    = if set, forces the plot window to this width
           YSIZE    = if set, forces the plot window to this height
           AUTO     = if set, turns auto-scaling on
           NOGAPS   = if set, eliminates data gap scanning
           NONOISE  = if set, filter out values outside 3 sigma from mean
           IGNORE_DISPLAY_TYPE = if set, causes the attribute display_type to
                                 be ignored.
           DEBUG    = if set, turns on additional debug output.
    	COLORBAR = if set, turns on a colorbar associated w/ each line
    	 	   being plotted. (TJK)
           NOSUBTITLE = if set, will not print 'time range = ' subtitle even after
                           the last graph. Needed for timetext case. RCJ
    	COMBINE = if set, need to add the dataset name to the y axis label
    		  added 10/14/2003 - TJK.
     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Tami Kovalick; April 24, 1997
    	Based on plot_timeseries.pro
     MODIFICATION HISTORY:

(See external/CDAWlib/plot_stack.pro)

## PLOT_TIMESERIES

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_TIMESERIES
     PURPOSE: To generate a time series plot given the anonymous structures
              returned by the read_mycdf function.
     CALLING SEQUENCE:
           out = read_mycdf(Xstruct,Ystruct)
     INPUTS:
           Xstruct = structure containing the Epoch variable structure of the
                     type returned by the read_mycdf structure.
           Ystruct = structure containing the variable to be plotted against
                     the Epoch variable in the Xstruct parameter
     KEYWORD PARAMETERS:
           TSTART   = Forces the time axis to begin at this Epoch time.
           TSTOP    = Forces the time axis to end at this Epoch time.
           ELEMENTS = if set, then only these elements of a dimensional variable
                      will be plotted.
           POSITION = If set, this routine will draw the plot(s) at this position
                      of an existing window, rather than open a new one.
           FIRSTPLOT= Use this key in conjunction with the position keyword. Set
                      this flag to indicate that the variable is the first in the
                      window.
           LASTPLOT = Use this key in conjunction with the position keyword. Set
                      this flag to indicate that the variable is the last in the
                      window.
           PANEL_HEIGHT = vertical height, in pixels, of each panel
           CDAWEB   = If set, the plot will have sufficient margin along the Z
                      axis to hold a colorbar.
           GIF      = If set, the plot will be a .gif file instead of Xwindow
           XSIZE    = if set, forces the plot window to this width
           YSIZE    = if set, forces the plot window to this height
           AUTO     = if set, turns auto-scaling on
           NOGAPS   = if set, eliminates data gap scanning
           NONOISE  = if set, filter out values outside 3 sigma from mean
       	ERR_PLUS = plus error bar value. If data is 1D error should be array of the same number
       	    	   of elements (example: data[65], err_plus[65]) or, if err_plus is the same value
       	           for all values of data: data[65], err_plus[1].
       	    	   If data is 2D: data[4,65], err_plus[4,65] or, if err_plus is the same value
       	    	   for all values of data, per row: data[4,65], err_plus[4],
       	    	   or per column: data[65,4], err_plus[4]
                      Warning: this keyword is overwritten by noerrorbars, if it is set.
       	ERR_MINUS= similar to err_plus.
           IGNORE_DISPLAY_TYPE = if set, causes the attribute display_type to
                                 be ignored.
    	NOSUBTITLE = if set, will not print 'time range = ' subtitle even after
                           the last graph. Needed for timetext case. RCJ
    	ONLYLABEL = if set, graph position is calculated but graph is not
    			plotted. However, the x-axis label *is* plotted.
    			Utilized by timetext case. RCJ
    	SCATTER = if set, display a scatter plot (each point is plotted as a
    		  dot, no lines connect the dots. added on 5/14/2001 TJK
           NOERRORBARS = if set, do not plot error bars, even if delta plus
                      and minus are defined.
    	COMBINE = if set, need to add the dataset name to the y axis label
    		  added 10/14/2003 - TJK.
           DEBUG    = if set, turns on additional debug output.
     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 22, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           8/13/96 : R. Burley    : Add NONOISE capability

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_timeseries.pro)

## PLOT_TIMETEXT

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_TIMETEXT
     PURPOSE: To generate a time text plot given the anonymous structures
              returned by the read_mycdf function.
     CALLING SEQUENCE:
           out = plot_timetext(Xstruct,Ystruct)
     INPUTS:
           Xstruct = structure containing the Epoch variable structure of the
                     type returned by the read_mycdf structure.
           Ystruct = structure containing the variable to be printed against
                     the Epoch variable in the Xstruct parameter
     KEYWORD PARAMETERS:
           TSTART   = Forces the time axis to begin at this Epoch time.
           TSTOP    = Forces the time axis to end at this Epoch time.
    	NOTIME	 = time is not displayed by timeaxis_text
    	NOSUBTITLE=subtitle is not displayed
    	PLABELOFFSET=Label offset in pixels
    	ONLYLABEL= only label will be displayed by timeaxis, no x-axis.
    	ELEMENTS = if set, then only these elements of a dimensional variable
                      will be plotted.
           NONOISE  = if set, filter out values outside 3 sigma from mean
    	NOVALIDS = if set, ignore validmin and validmax from input structures
    	COMBINE = if set, need to add the dataset name to the y axis label
    		  added 10/24/2003 - TJK.
           DEBUG    = if set, turns on additional debug output.
     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Created 11/99 by RCJ. Based on plot_timeseries.pro
     MODIFICATION HISTORY:
           10/24/2003 - TJK added COMBINE keyword to add dataset name label

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_timetext.pro)

## PLOT_WIND_MAP

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PLOT_WIND_MAP
     PURPOSE: To plot the map image data given in the input parameter astruct.
              Can plot as "thumbnails" or single frames.
     CALLING SEQUENCE:
           out = plot_map_images(astruct,vname)
     INPUTS:
           astruct = structure returned by the read_mycdf procedure.
           vname   = name of the variable in the structure to plot

     KEYWORD PARAMETERS:
           THUMBSIZE = size (pixels) of thumbnails
           FRAME     = individual frame to plot
           XSIZE     = x size of plotting window, single frame or thumbnails: 512 is default
       	YSIZE	  = for thumbnails:  calculated based on the number of images to plot.
       	    	    for single frames: 512 is default
           GIF       = name of gif file to send output to
           PNG      = name of png file to send output to
           REPORT    = name of report file to send output to
           TSTART    = time of frame to begin mapping, default = first frame
           TSTOP     = time of frame to stop mapping, default = last frame
           CDAWEB    = being run in cdaweb context, nothing happens. yet.
           DEBUG    = if set, turns on additional debug output.

     OUTPUTS:
           out = status flag, 0=0k, -1 = problem occured.
     AUTHOR:
           Rita Johnson 12/2004. Based on plot_map_images.pro
     MODIFICATION HISTORY:

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/plot_wind_map.pro)

## PROJECT_SUBTITLE

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PROJECT_SUBTITLE
     PURPOSE: Examine the structure given by the input parameter, and return
              a string to be used as a subtitle giving project information,
              and write this string onto current plot.
     CALLING SEQUENCE:
           project_subtitle,a,title
     INPUTS:
           a = structure containing a variable from the type of structure
               returned by the read_mycdf procedure.
     OUTPUTS:
           title = the string written to the plot or gif.
     KEYWORD PARAMETERS:
           IMAGE    = special processing for image-type displays
           TIMETAG  = epoch value associated with a single image
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 22, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           8/7/96  R.Burley    ; Add TIMETAG keyword
         10/21/97  R.Baldwin   ; Add SSCWEB keyword
         01/29/98  R.Baldwin   ; Added TCOLOR keyword
         10/14/98  T. Kovalick ; Added the acknowledgements line.
         05/16/01  T. Kovalick ; Added carriage return after ISTP line since
    			      it was running of the page.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/project_subtitle.pro)

## READ_MYCDF[10]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: READ_MYMETADATA
     PURPOSE:
    	To read all of the attribute values for the requested variable, and
           to return this information as an anonymous structure.
     CALLING SEQUENCE:
           metadata = read_mymetadata(vname,CDFid)
     INPUTS:
           vname = string, name of variable whose metadata is being read
           CDFid = integer, id of already opened CDF file
     KEYWORD PARAMETERS:
     OUTPUTS:
           metadata = anonymous structure whose tags are the attribute names
                      and whose fields are the corresponding attribute values.
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[11]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: check_ifclone.
     PURPOSE:
            Check if a particular variable is a 'clone' of another variable.
     CALLING SEQUENCE:
    	result = check_ifclone (variable_name, id)
     INPUTS:
    	variable_name = name of a CDF variable as a string
       id = CDF id of an open CDF.
     KEYWORD PARAMETERS:
     OUTPUTS:
           Either the empty string ('') if is not a cloned variable or the
           the name of the source variable (defined in the COMPONENT_0
           attribute) if is a clone variable.
     AUTHOR:
           Ron Yurow, April 19, 2018
     MODIFICATION HISTORY:

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[12]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Getvar_attribute_names CDFid
     PURPOSE:
    	To return all of the attribute names for the requested variable, as
    	an array.
     CALLING SEQUENCE:
           att_array = getvar_attribute_names(vname,CDFid, ALL=ALL)
     INPUTS:
           CDFid = integer, id of already opened CDF file
     KEYWORD PARAMETERS:
    	ALL - all attributes are returned
    	      default is that just variable scoped attributes are returned
     OUTPUTS:
           att_array = string array of attribute names
     AUTHOR:
           Tami Kovalick
           tami.kovalick@gsfc.nasa.gov    (301)286-9422
     MODIFICATION HISTORY:

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[13]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: GET_NUMALLVARS
     PURPOSE:
     	To return the total number of variables in the cdf.

     CALLING SEQUENCE:
           num_vars = get_numallvars(CNAME=CNAME)
     INPUTS:
     KEYWORD PARAMETERS:
    	CNAME = string, name of a CDF file to be opened and read
    	CDFid = integer, id of an already opened CDF file
     OUTPUTS:
           num_vars = number of variables in the CDF
     AUTHOR:
           Tami Kovalick, RITSS, October 27, 2000
     MODIFICATION HISTORY:

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[14]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: GET_ALLVARNAMES
     PURPOSE:
     	To return a string array containing the names of all of the
    	variables in the given CDF file.
     CALLING SEQUENCE:
           vnames = get_allvarnames()
     INPUTS:
     KEYWORD PARAMETERS:
    	CNAME = string, name of a CDF file to be opened and read
    	CDFid = integer, id of an already opened CDF file
           VAR_TYPE = string, only return the names for variables who have an
                      attribute called 'VAR_TYPE' and whose value matches the
                      value given by this keyword.  (ex. VAR_TYPE='data')
     OUTPUTS:
           vnames = string array of variable names
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
    	4/9/1998 - TJK modified to include all variable when the "var_type"
    	keyword isn't used.  The original code only included variables
    	that vary by record so some important "support_data" variables
    	were being thrown out.
           5/1/2018 - TJK modified to check if no attributes and var_type
           attribute don't exist, don't look for them as these error out.

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[15]

[Previous Routine] [Next Routine] [List of Routines]

     RCJ 03/30/2012  Commented out this function. It was called once and that
      call is commented out too.
    ;check the variables_comp array for existence of the variable name, for
    ;the current cdf.
    function check_varcompare, variables_comp, cdf_index, variable_name
    ;print,'**** ' & help,variables_comp
    ;print, variable_name, cdf_index, variables_comp
    ;stop;
    x = where(variable_name eq variables_comp(cdf_index,*), xcnt)
    if (xcnt gt 0)then print, variable_name, ' found 1' else print, variable_name, ' not found 0'
    if (xcnt gt 0)then return, 1 else return, 0
    end

    +------------------------------------------------------------------------
     NAME: READ_MYCDF
     PURPOSE:
    	Read all data and metadata for given variables, from given CDF
           files, and return all information in a single anonymous structure
           of the form:
              structure_name.variable_name.attribute_name.attribute_value

     CALLING SEQUENCE:
           out = read_mycdf(vnames,cnames)
     INPUTS:
           vnames = string, array of variable names or a single string of
                    names separated by a comma.  (ex. 'Epoch,Magfld,Bmax')
           cnames = string, array of CDF filenames or a single string of
                    names separated by a comma.
     KEYWORD PARAMETERS:
    	ALL = 0: get data and metadata for requested variable(s) only.
                 1: get data and metadata for ALL variables in the CDFs.
                 2: get data and metadata for all var_type='data' variables.
           NODATASTRUCT = If set, instead of returning the data for each variable
                       in the 'DAT' attribute field, create a 'HANDLE' field
                       and set it to the handle id of a data handle which
                       holds the data for each variable.
           NOQUIET = If set, do NOT set the !QUIET system variable before
                     reading the cdf file(s).
           DEBUG = If set, print out some progress information during reading.
    	TSTART = epoch starting value - YYYYMMDD etc. string.
    	TSTOP = epoch ending value - YYYYMMDD etc. string.
     OUTPUTS:
           out = anonymous structure holding all data and metadata for the
                 requested variables. If an error occurs, that we know how
                 to deal w/, an alternate structure is returned, its structure
    	      is as follows: ('DATASET',d_set,'ERROR',v_err,'STATUS',v_stat)

     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
    	Tami Kovalick, HSTX, 12/16/96 modified to verify whether
     variables requested in vnames array are actually in the "data" cdfs
     prior to requesting the data from these variables.  If variables
     aren't valid then they are removed from the vnames array and the
     code continues on to create a valid structure.
    	Tami Kovalick, HSTX, 12/20/96 modified to allow the use of
     TSTART and TSTOP keywords (see above).  Use of these keywords will
     force the code to only read the necessary records in the CDF, otherwise
     the code will read the entire CDF.  Could enhance the code to deal
     w/ one or the other keyword - right now they are only used if both
     are set.
    	Tami Kovalick, RSTX, 02/13/98, Carrie Gallap started modifications
     to read_myCDF to accommodate "virtual variables" (VV) .  Tami finished
     up the code and made corrections to several sections.  One new routine was
     written add_myCOMPONENTS, this routine is called when a valid virtual
     variable is found in order to add any additional variables needed for
     actually generating the data for the VV.  The routine looks for variable
     attributes w/ the naming convention COMPONENT_n where n is a digit.  The
     basic methodology to the changes is to determine whether any of the
     variables selected are virtual variables, if so then the variable name
     and the source (where the VV was defined - master or data cdfs) are
     stored in a structure called vir_vars, then add the component variables
     to the vnames array.  Do the usual checking to see if the variables requested
     in vnames actually exist. Then continue on w/ getting the metadata for all
     variables (including VV), and continue on w/ the getting the data from
     the CDFs for all variables except the VV.  Population of the VV's data field
     in the "burley" structure are handled at the very end in a case statement
     which looks for each VV's variable attribute FUNCTION to determine which
     actual "IDL function" to call, ie. conv_pos.

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[1]

[Previous Routine] [Next Routine] [List of Routines]

     This package of IDL functions facilitates reading data and metadata from
     Common Data Format (CDF) files.  While CDF provides all the benefits
     of a portable, self-documenting scientific data format, reading them is
     not always a simple matter.  To make it simple, I have created this IDL
     package so that all of the data and metadata from multiple variables can
     be read from multiple CDF files ... in one single, simple command.  The
     function is called 'READ_MYCDF' and it returns an anonymous structure of
     the form:

           structure_name.variable_name.attribute_name.attribute_value

     From this structure, all data and metadata for the requested variables
     is easily accessed.

     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864

     NOTES:

     Three additional 'attributes' will be included in the sub-structure for
     each variable.  The first is the 'VARNAME' field.  Because IDL structure
     tags are always uppercase, and because CDF variable names are case sen-
     sitive, a case sensitive copy of the variable name is created.  The second
     'attribute' to be added is the 'CDFTYPE' field.  This field will hold a
     string value holding the cdf data type.  The last 'attribute' to be
     artificially added will be either the 'DAT' field or, if the keyword
     NODATASTRUCT is set, the 'HANDLE' field.  The 'DAT' field will contain
     the actual data values read from the CDF's for the variable.  The 'HANDLE'
     field will hold a handle_id where the data will reside.

     This package will look for and utilize certain special attributes required
     by the International Solar Terrestrial Physics Key Parameters Generation
     Software Standards and Guidelines.  The existance of these attributes is
     not required for the operation of this software, but will enhance its
     usefullness, primarily by reading variables that will be needed for proper
     utilization of the data, even though you may not have asked for them
     explicitly.

     This package was tested under IDL version 4.0.1b.  This package was tested
     on CDF's up to version 2.5 and on both r-variables and z-variables.

     CDF variables defined as unsigned integers are, unfortunately, currently
     returned by the IDL CDF_VARGET procedure as signed integers.  This can
     cause sign flips.  This software detects and corrects for this defect for
     data values.  However, it cannot detect and correct for this defect for
     attribute values because the IDL procedure CDF_ATTINQ does not return the
     CDF data type of the attribute.  These problems have been reported to
     RSI.

     Modifications:
    	As of October 2, 2000, this software can run on all of the following
    	IDL versions, 5.1, 5.2 and 5.3 (testing for 5.4 will commence soon).
    	Some fairly major changes were necessary in order for read_myCDF
    	to work under 5.3.  IDL 5.3 enforces the variable naming rules for
    	structure tag names.  This change affects this s/w because we basically
    	had never checked our tag names, e.g. we used the CDF variable names
    	and label attribute values directly.  So in read_myCDF the general
    	concept to fixing this problem was to set up a table (which is shared
    	in a common block - not my favorite way to go, but definitely the
    	easiest), where there are two tags, equiv and varname.  varname
    	contains the real CDF variable name, equiv contains the "cleaned up,
    	IDL acceptable" variable name that can be used as a structure tag
    	name... TJK 04/02/2000

     1996, NASA/Goddard Space Flight Center
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

     Added forward declaration so that we can use this in read_myVARIABLE.
     Ron Yurow (July 13, 2018)
    ORWARD_FUNCTION get_allvarnames

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[2]

[Previous Routine] [Next Routine] [List of Routines]

     Search the tnames array for the instring, returning the index in tnames
     if it is present, or -1 if it is not.
    TJK this function is in a separate file called TAGindex.pro
    since its called from many different routines in this system.
    FUNCTION TAGindex, instring, tnames
    instring = STRUPCASE(instring) ; tagnames are always uppercase
    a = where(tnames eq instring,count)
    if count eq 0 then return, -1 $
    else return, a(0)
    end

    +------------------------------------------------------------------------
     NAME: AMI_ISTPPTR
     PURPOSE:
           Return true(1) or false(0) depending on whether or not the
           given attribute name qualifies as an ISTP pointer-class attribute.
     CALLING SEQUENCE:
    	out = amI_ISTPptr(attribute_name)
     INPUTS:
    	attribute_name = name of a CDF attribute as a string
     KEYWORD PARAMETERS:
     OUTPUTS:
           True(1) or False(0)
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: AMI_VAR
     PURPOSE:
           Return true(1) or false(0) depending on whether or not the
           given attribute name's value is assigned to a real CDF variable name.
     CALLING SEQUENCE:
    	out = amI_VAR(attribute_name)
     INPUTS:
    	attribute_name = name of a CDF attribute as a string
     KEYWORD PARAMETERS:
     OUTPUTS:
           True(1) or False(0)
     AUTHOR:
    	Tami Kovalick	March 6, 2000

     MODIFICATION HISTORY:

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[3]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: RECAST_CDF_TYPE
     PURPOSE:
           Return a copy of val recast to the requested type.  If it is not
           possible to convert type, then val is returned un-altered.
     CALLING SEQUENCE:
    	new = RECAST_CDF_TYPE (val, new_type)
     INPUTS:
    	val = value to convert.
       new_type = CDF type to convert value to.
     KEYWORD PARAMETERS:
     OUTPUTS:
           val converted to the requested type.
     AUTHOR:
           Ron Yurow,
     MODIFICATION HISTORY:
           Original version.  June 7, 2018

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[4]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: AMI_ISTPVATTRIB
     PURPOSE:
           Return true(1) or false(0) depending on whether or not the
           given attribute name qualifies as an ISTP variable atrribute.
     CALLING SEQUENCE:
    	out = amI_ISTPVattrib(attribute_name)
     INPUTS:
    	attribute_name = name of a CDF attribute as a string
     KEYWORD PARAMETERS:
     OUTPUTS:
           True(1) or False(0)
     AUTHOR:
           Ron Yurow, March 8, 2018
     MODIFICATION HISTORY:

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[5]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: APPEND_MYDATA
     PURPOSE:
     	Append the 'new' data to the 'old' data using array concatenation.
     CALLING SEQUENCE:
           out = append_mydata(new,old)
     INPUTS:
           new = data to be appended to the old data
           old = older data that new data is to be appended to
     KEYWORD PARAMETERS:
     OUTPUTS:
           out = product of concatenating the old and new data arrays
     NOTES:
     	Special case check: if old data was from either a skeleton CDF or from
     	a CDF with only a single record, then the last dimension was dropped
    	during the process of saving/retrieving the data from a handle.
    	Must compare the dimensionality of the new and old data to determine
    	if this drop has occured, and if so, reform the old data to include
           the extra dimension so that the data can be appended.
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[6]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: add_myDEPENDS
     PURPOSE:
    	Search the metadata anonymous structure for ISTP 'DEPEND'
    	attributes and add the variable name that it points to to the
           vnames array if it is not already present.  If the DEPEND
    	variable is not present in the list, change the data_type so it
    	won't be plotted.

     CALLING SEQUENCE:
           add_myDEPENDS, metadata, vnames

     INPUTS:
           metadata = anonymous structure holding attribute values
           vnames   = string array of virtual variables found

     OUTPUTS:
           vnames    = modified variable name that includes component variable
                       names

     NOTES - this is similar to follow_mydepends, except it does less.

     AUTHOR:
     	Tami Kovalick, QSS,   11/29/2006

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[7]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: add_myCOMPONENTS
     PURPOSE:
    	Search the metadata anonymous structure for ISTP 'COMPONENT'
    	attributes and add the variable name that it points to to the
           vnames array if it is not already present.  If the component
    	variable is not present in the list, change the data_type so it
    	won't be plotted.

     CALLING SEQUENCE:
           add_myCOMPONENTS, metadata, vnames

     INPUTS:
           metadata = anonymous structure holding attribute values
           vnames   = string array of virtual variables found

     OUTPUTS:
           vnames    = modified variable name that includes component variable
                       names

     AUTHOR:
     	Carrie Gallap, Raytheon STX,   1/5/98

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[8]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: READ_MYVARIABLE
     PURPOSE:
    	Return the data for the requested variable.
     CALLING SEQUENCE:
           out = read_myvariable(vname, CDFid, vary, dtype, recs)
     INPUTS:
           vname = string, name of variable to be read from the CDF
           CDFid = integer, id or already opened CDF file.
     KEYWORD PARAMETERS:
    	START_REC = first record to read.
    	REC_COUNT = number of records to read.
       MAKE_VARY= Requesting non-existent records may result in
           the pad value being returned.  Because conversion of a NRV variable to
           record varing will likely result in a request for non-existent
           records, setting this flag will cause the initial record (which is
           guaranteed to be valid) to all subsequent records.

     OUTPUTS:
           out = all data from the CDF for the variable being read
           vary = True(1) or False(0) is variable record-varying
           dtype= string, CDF data type
           recs = integer, number of data records
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           96/04/11 : R.Burley :zVar handling when MAXRECS = -1 changed to
                                read REC_COUNT of MAXRECS + 2 & return,DAT
     	96/12/20 ; T. Kovalick modified to take START_REC and REC_COUNT
    	keywords (see above).  If they aren't set you will get all of
     	the records in a cdf.
           (Sep 30, 2019) : R. Yurow added new keyword MAKE_VARY.  See above.

(See external/CDAWlib/read_myCDF.pro)

## READ_MYCDF[9]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: READ_MYATTRIBUTE
     PURPOSE:
    	Return the value of the requested attribute for the requested variable.
     CALLING SEQUENCE:
           out = read_myattribute(vname,anum,CDFid)
     INPUTS:
           vname = string, name of variable whose attribute is being read
           anum = integer, number of attribute being read
           CDFid = integer, id of already opened CDF file.
     KEYWORD PARAMETERS:
     OUTPUTS:
           out = anonymous structure holding both the name of the attribute
                 and the value of the attribute
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864

     MODIFICATION HISTORY:
       	RCJ 11/2003 Added keyword isglobal

(See external/CDAWlib/read_myCDF.pro)

## READ_MYNETCDF[1]

[Previous Routine] [Next Routine] [List of Routines]

     This package of IDL functions facilitates reading data and metadata from
     Net Common Data Format (NCDF) files.
     While NCDF provides all the benefits
     of a portable, self-documenting scientific data format, reading them is
     not always a simple matter.  To make it simple, I have created this IDL
     package so that all of the data and metadata from multiple variables can
     be read from multiple NCDF files ... in one single, simple command.  The
     function is called 'READ_MYNETCDF' and it returns an anonymous structure of
     the form:

           structure_name.variable_name.attribute_name.attribute_value

     From this structure, all data and metadata for the requested variables
     is easily accessed.

     AUTHOR:
           Tami Kovalick, NASA/GSFC/Code 672.0, Spring 2017

     NOTES:

     For starters, this is a copy of read_myCDF with all cdf read
     routines replaced by netcdf read routines.  Hopefully this will get
     us most of the way there to having a good reader that produces the desired
     output structure.  Generic routines already in read_myCDF were
     removed from read_myNETCDF such as break_mystring, ami_istpptr,
     follow_mydepends, etc.

     Three additional 'attributes' will be included in the sub-structure for
     each variable.  The first is the 'VARNAME' field.  Because IDL structure
     tags are always uppercase, and because NCDF variable names are case sen-
     sitive, a case sensitive copy of the variable name is created.  The second
     'attribute' to be added is the 'NCDFTYPE' field.  This field will hold a
     string value holding the ncdf data type.  The last 'attribute' to be
     artificially added will be either the 'DAT' field or, if the keyword
     NODATASTRUCT is set, the 'HANDLE' field.  The 'DAT' field will contain
     the actual data values read from the NCDF's for the variable.  The 'HANDLE'
     field will hold a handle_id where the data will reside.

     This package will look for and utilize certain special attributes required
     by the International Solar Terrestrial Physics Key Parameters Generation
     Software Standards and Guidelines.  The existance of these attributes is
     not required for the operation of this software, but will enhance its
     usefullness, primarily by reading variables that will be needed for proper
     utilization of the data, even though you may not have asked for them
     explicitly.

     This package was tested under IDL version 8.5.  This package was tested
     on NCDF's up to version 4 and master cdfs of versionm 3.6.4.

     NCDF variables defined as unsigned integers are, unfortunately, currently
     returned by the IDL NCDF_VARGET procedure as signed integers.  This can
     cause sign flips.  This software detects and corrects for this defect for
     data values.  However, it cannot detect and correct for this defect for
     attribute values because the IDL procedure NCDF_ATTINQ does not return the
     NCDF data type of the attribute.  These problems have been reported to
     RSI.

     Modifications:

     1996, NASA/Goddard Space Flight Center
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/read_mynetcdf.pro)

## READ_MYNETCDF[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: READ_MYVARIABLE_netcdf
     PURPOSE:
    	Return the data for the requested variable.
     CALLING SEQUENCE:
           out = read_myvariable_netcdf(vname, NCDFid, vary, dtype, recs)
     INPUTS:
           vname = string, name of variable to be read from the NCDF
           NCDFid = integer, id or already opened NCDF file.
     KEYWORD PARAMETERS:
    	START_REC = first record to read.
    	REC_COUNT = number of records to read.
     OUTPUTS:
           out = all data from the NCDF for the variable being read
           vary = True(1) or False(0) is variable record-varying
           dtype= string, NCDF data type
           recs = integer, number of data records
     AUTHOR:
           Tami Kovalick, NASA/GSFC/Code 672

     MODIFICATION HISTORY:

(See external/CDAWlib/read_mynetcdf.pro)

## READ_MYNETCDF[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: READ_MYATTRIBUTE_netcdf
     PURPOSE:
    	Return the value of the requested attribute for the requested variable.
     CALLING SEQUENCE:
           out = read_myattribute_netcdf(vname,anum,NCDFid,isglobal=isglobal)
     INPUTS:
           vname = string, name of variable whose attribute is being read
           anum = integer, number of attribute being read
           NCDFid = integer, id of already opened NCDF file.
     KEYWORD PARAMETERS:
           isglobal = true (global attribute requested, otherwise variable)
     OUTPUTS:
           out = anonymous structure holding both the name of the attribute
                 and the value of the attribute
     AUTHOR:
           Tami Kovalick, NASA/GSFC/Code 672

     MODIFICATION HISTORY:

(See external/CDAWlib/read_mynetcdf.pro)

## READ_MYNETCDF[3]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: READ_MYMETADATA_netcdf
     PURPOSE:
    	To read all of the attribute values for the requested variable, and
           to return this information as an anonymous structure.
     CALLING SEQUENCE:
           metadata = read_mymetadata_netcdf(vname,NCDFid)
     INPUTS:
           vname = string, name of variable whose metadata is being read
           NCDFid = integer, id of already opened NCDF file
     KEYWORD PARAMETERS:
     OUTPUTS:
           metadata = anonymous structure whose tags are the attribute names
                      and whose fields are the corresponding attribute values.
     AUTHOR:
           Tami Kovalick, NASA/GSFC/Code 672

     MODIFICATION HISTORY:

(See external/CDAWlib/read_mynetcdf.pro)

## READ_MYNETCDF[4]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: ncdf_getvar_attribute_names NCDFid
     PURPOSE:
    	To return all of the attribute names for the requested variable, as
    	an array.
     CALLING SEQUENCE:
           att_array = ncdf_getvar_attribute_names(vname,NCDFid, ALL=ALL)
     INPUTS:
           NCDFid = integer, id of already opened NCDF file
     KEYWORD PARAMETERS:
    	ALL - all attributes are returned
    	      default is that just variable scoped attributes are returned
     OUTPUTS:
           att_array = string array of attribute names
     AUTHOR:
           Tami Kovalick

     MODIFICATION HISTORY:

(See external/CDAWlib/read_mynetcdf.pro)

## READ_MYNETCDF[5]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: GET_NUMALLVARS_netcdf
     PURPOSE:
     	To return the total number of variables in the ncdf.

     CALLING SEQUENCE:
           num_vars = get_numallvars_netcdf(CNAME=CNAME)
     INPUTS:
     KEYWORD PARAMETERS:
    	CNAME = string, name of a NCDF file to be opened and read
    	NCDFid = integer, id of an already opened NCDF file
     OUTPUTS:
           num_vars = number of variables in the NCDF
     AUTHOR:
           Tami Kovalick

     MODIFICATION HISTORY:

(See external/CDAWlib/read_mynetcdf.pro)

## READ_MYNETCDF[6]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: GET_ALLVARNAMES_netcdf
     PURPOSE:
     	To return a string array containing the names of all of the
    	variables in the given NCDF file.
     CALLING SEQUENCE:
           vnames = get_allvarnames_netcdf()
     INPUTS:
     KEYWORD PARAMETERS:
    	CNAME = string, name of a NCDF file to be opened and read
    	NCDFid = integer, id of an already opened NCDF file
           VAR_TYPE = string, only return the names for variables who have an
                      attribute called 'VAR_TYPE' and whose value matches the
                      value given by this keyword.  (ex. VAR_TYPE='data')
     OUTPUTS:
           vnames = string array of variable names
     AUTHOR:
           Tami Kovalick, NASA/GSFC/Code 672
     MODIFICATION HISTORY:

(See external/CDAWlib/read_mynetcdf.pro)

## READ_MYNETCDF[7]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: READ_MYNETCDF
     PURPOSE:
    	Read all data and metadata for given variables, from given NCDF
           files, and return all information in a single anonymous structure
           of the form:
              structure_name.variable_name.attribute_name.attribute_value

     CALLING SEQUENCE:
           out = read_mynetcdf(vnames,cnames)
     INPUTS:
           vnames = string, array of variable names or a single string of
                    names separated by a comma.  (ex. 'Epoch,Magfld,Bmax')
           cnames = string, array of NCDF filenames or a single string of
                    names separated by a comma.
     KEYWORD PARAMETERS:
    	ALL = 0: get data and metadata for requested variable(s) only.
                 1: get data and metadata for ALL variables in the NCDFs.
                 2: get data and metadata for all var_type='data' variables.
           NODATASTRUCT = If set, instead of returning the data for each variable
                       in the 'DAT' attribute field, create a 'HANDLE' field
                       and set it to the handle id of a data handle which
                       holds the data for each variable.
           NOQUIET = If set, do NOT set the !QUIET system variable before
                     reading the ncdf file(s).
           DEBUG = If set, print out some progress information during reading.
    	TSTART = epoch starting value - YYYYMMDD etc. string.
    	TSTOP = epoch ending value - YYYYMMDD etc. string.
     OUTPUTS:
           out = anonymous structure holding all data and metadata for the
                 requested variables. If an error occurs, that we know how
                 to deal w/, an alternate structure is returned, its structure
    	      is as follows: ('DATASET',d_set,'ERROR',v_err,'STATUS',v_stat)

     AUTHOR:
           Tami Kovalick - ADNET - September 2016
     MODIFICATION HISTORY:
    	Tami Kovalick - this is based on read_myCDF, but should read
                           netcdfs.

(See external/CDAWlib/read_mynetcdf.pro)

## RECTIFY_DATA

[Previous Routine] [Next Routine] [List of Routines]

     This package of IDL functions facilitates data processing by applying
     error checking and data normalization procedures to the structure that
     is returned by read_myCDF.

(See external/CDAWlib/rectify_data.pro)

## RUNLENGTH

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           RUNLENGTH
     PURPOSE:
           Give run lengths for array values.
     CATEGORY:
     CALLING SEQUENCE:
           y = runlength(x,[r])
     INPUTS:
           x = 1-d array of values.                  in
     KEYWORD PARAMETERS:
     OUTPUTS:
           y = X with multiple values squeezed out.  out
           r = run length of each element in Y.      out
     COMMON BLOCKS:
     NOTES:
     MODIFICATION HISTORY:
           RES  30 Jan, 1986.
           R. Sterner, 25 Sep, 1990 --- converted to IDL V2.
           Johns Hopkins University Applied Physics Laboratory.

     Copyright (C) 1986, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/viscal.pro)

## SEMIMINMAX

[Previous Routine] [Next Routine] [List of Routines]

     NAME: semiMinMax
     PURPOSE: For array y, return min and max values within 3 standard
              deviations from the mean
     CALLING SEQUENCE:
           semiMinMax, y, ymin, ymax
     INPUTS:
           y = array of 4 or more elements
     KEYWORD PARAMETERS:
           MODIFIED = use modified sigma which uses kurt. & skew.
                      results in a more liberal acceptance of data
     OUTPUTS:
           ymin = minimum value within 3 stdev's of mean
           ymax = maximum value within 3 stdev's of mean
     AUTHOR: ?
     MODIFICATION HISTORY:
       10/96 R.Baldwin; replaced stdev w/ moment
       03/99 R.Baldwin; added MODIFIED keyword

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/semiminmax.pro)

## SPDF_READ_UTILITIES[1]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: PARSE_DISPLAY_TYPE
     PURPOSE:
    	Parse and examine the input string.  It should be the value of the
    	CDF attribute 'DISPLAY_TYPE'.  Return an array of variable names
           that it 'points' to.
     CALLING SEQUENCE:
    	out = parse_display_type(instring)
     INPUTS:
           instring = string, value of a CDF attribute called 'DISPLAY_TYPE'
     KEYWORD PARAMETERS:
     OUTPUTS:
           out = string array, names of other variables required for display
     NOTES: This routine expects to find 'DISPLAY_TYPE' values looking like:
            PLOT_TYPE>x=vname,y=vname ...
            PLOT_TYPE>y=vname,z=vname(*,1),z=vname(*,2) ...
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
    TJK modified 01/27/98 to not parse orbit display type here - the items
    specified for the orbit plot type aren't additional variables.
    TJK modified 09/25/2001 to not parse the "symsize" keyword because its
    value isn't a variable.

(See external/CDAWlib/spdf_read_utilities.pro)

## SPDF_READ_UTILITIES[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: follow_mydepends
     PURPOSE:
    	Search the metadata anonymous structure for ISTP 'DEPEND' attributes.
           If and when found, add the variable name that it points to to the
           vnames array if it is not already present, and increase the size
           of the dhids and mhids arrays.
     CALLING SEQUENCE:
           follow_mydepends, metadata, vnames, dhids, mhids
     INPUTS:
           metadata = anonymous structure holding attribute values
           vnames   = string array of the names of variables already processed
           vvarys   = string array of the record variance for each variable
           dhids    = array of data handle id's
           mhids    = array of metadata handle id's
           dlstid   = array of handle id's. Each points to a list of dependent variables.
     KEYWORD PARAMETERS:
           DEPEND0  = array of flags do indicate if the variables is referenced by
                      the DEPEND_0 attribute of another variable.
     OUTPUTS:
           dhids    = array of data handle id's
           mhids    = array of metadata handle id's
           dlstid   = array of handle id's. Each points to a list of dependent variables.
     AUTHOR:
           Richard Burley, NASA/GSFC/Code 632.0, Feb 13, 1996
           burley@nssdca.gsfc.nasa.gov    (301)286-2864
     MODIFICATION HISTORY:
           Added parameter dlstid   (Ron Yurow 11/16/2018)
           Moved the routine from the read_myCDF.pro file to
           the spdf_read_utilities.pro file (TJK 11/21/2018)

(See external/CDAWlib/spdf_read_utilities.pro)

## SPECTROGRAM

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           Spectrogram

     PURPOSE:
           This function plots a color spectrogram of Z in contiguous or
           non-contiguous blocks with color Z(i,j) (data Z(i,j) is shown as a box
           of size Xmin(i):Xmax(i) and Ymin(j):Ymax(j) with color Z(i,j))

     CATEGORY:
           Graphics

     CALLING SEQUENCE:
           SPECTROGRAM, Z, [X, Y]
           SPECTROGRAM, Z, Xmin, Ymin, Xmax, Ymax
           SPECTROGRAM, Z, Xcenter, Ycenter, Xminus, Yminus, Xplus, Yplus

     INPUTS:
           Z:      2-dimensional data array; converted to float or double for NAN use

     OPTIONAL INPUTS:
           X:      1-dimensional data array of size Z[*,0] or 2-dim of size Z[*,*]
           Y:      1-dimensional data array of size Z[0,*] or 2-dim of size Z[*,*]

           Xmin:   1- or 2- dim array of X values for left side of each data box
           Ymin:   1- or 2- dim array of Y values for bottom side of each data box
           Xmax:   1- or 2- dim array of X values for right side of each data box
           Ymax:   1- or 2- dim array of Y values for top side of each data box

           Xcenter:1- or 2- dim array of X values for center side of each data box
           Ycenter:1- or 2- dim array of Y values for center side of each data box
           Xminus: Xcenter-Xminus defines left side of each data box
           Yminus: Ycenter-Yminus defines bottom side of each data box
           Xplus:  Xcenter+Xplus defines right side of each data box
           Yplus:  Ycenter+Yplus defines top side of each data box
           (this allows gaps or overlaps in boxes; if not desired, use Z,X,Y case)

     KEYWORD PARAMETERS:
           COLORBAR=colorbar:  Switch to create color bar on right
           CSCALE=cScale:  scale for colorbar range [min, max]; sets /colorbar
           CTITLE=cTitle:  String title for colorbar
           CCHARSIZE=cCharSize:    Character size for axis on color bar
           LOGZ=logZ:      Scale Z data and color scale logarithmically
           LOGX=logX:      Scale Y axis logarithmically
           LOGY=logY:      Scale Y axis logarithmically
           CENTER=center:  Center boxes on (X,Y) location (only for 3 parameter
                                   case: spectrogram, Z, X, Y, /center)
           CENTERX=centerX:  Center boxes in X direction (only for 3 parameter
                                   case: spectrogram, Z, X, Y, /centerX)
           CENTERY=centerY:  Center boxes in Y direction (only for 3 parameter
                                   case: spectrogram, Z, X, Y, /centerY)
           FILLVALUE=fillValue: Z data with this value are ignored
           YFILLVALUE=YfillValue: Y data with this value are ignored
           XFILLVALUE=XfillValue: X data with this value are ignored
           MAXVALUE=maxValue: Max value of data to plot; values above are ignored
           MINVALUE=minValue: Min value of data to plot; values below are ignored
               [probably better to use cScale so extremas are colored not ignored]
           NRESCOL=nResCol: number of colors to reserve outside color table, def=2
           NOSKIPGAPS=noSkipGaps: Turns off treating large delta X as missing data
                   and skip; not done anyway if Center option selected
                   #### Also assumes 1-dim X array
           NOYSKIPGAPS=noYSkipGaps: Turns off treating large delta Y as missing data
           QUICK=quick:    Allow quick and dirty plotting ignoring X and Y sizes
                                   (for X and Z plot devices only)
           REDUCE=reduce: Reduce the number of X values to polyfill to not more
                             than twice the number of pixels across the plot, by
                             sampling every so many values; for non-Postscript
                             devices only; done for speed, alternative to /quick
           NOCLIP=noclip:  Polyfill bug in Z device; defaults to noclip=0
           STATUS=status:  Return 0 if plot okay, else -1 for an error,
                             status variable must be predefined before call
           _EXTRA=extra:   Any extra parameters to pass on to plot outline
                             Add your own title, xtitle, ytitle
                     May be able to over-ride plot location/size with position

     OUTPUTS:
           No outputs.

     COMMON BLOCKS:
           DEVICETYPEC: deviceType
           Shared with DeviceOpen.pro to allow inverting grayscale Postscript

     SIDE EFFECTS:
           Creates plot to screen or file.

     RESTRICTIONS:
           Sets a specific X margin to allow for the colorbar.
           Forces input arrays to float or double

     SUBROUTINES:
           Calls colorbar.pro, findgaps.pro, align_center.pro

     PROCEDURE:
           Uses plot,/nodata to setup the plot area and then uses polyfill to
           on each data value to color each small square of the spectrogram
           A colorbar is plotted on the right if cscale is set.

     EXAMPLE:
           Create a spectrogram plot of 2 dimensional data Z = dist(50)
           spectrogram, dist(50), /colorbar
           spectrogram,dist(50),findgen(50),findgen(50)+1,findgen(50),findgen(50)+1

     MODIFICATION HISTORY:
           Written by:     Bobby Candey, NASA GSFC Code 632, 1993 August 27
                   Robert.M.Candey.1@gsfc.nasa.gov
           1993 Nov 9      BC, removed timeaxis call and made more generic
           1994 Sept 19    BC, update with documentation and higher level routine
           1994 Nov 28     BC, added handling of 2-dim X and Y
           1994 Dec 6      BC, merged routines and added center-minus-plus option
           1995 April 10   BC, completed initial coding of version 5
           1995 Jun 22     BC, added smaller font size for color bar axis
           1995 July 26    BC, added cCharSize and reforming
           1995 Oct 11     BC, added min/maxValue scaling to bytscl
           1996 March 17   BC, added skip over time gaps and added fillValue
           1996 March 18   BC, added /reduce for speed plotting
           1996 March 25   BC, added noclip keyword for Z device bug with polyfill
           1996 April 8    BC, added status keyword and plot a blank on all fill
           1996 April 16   BC, moved Cscale to override min/maxValue
           1996 April 17   BC, added colorBar switch to allow autoscale
           1996 August 28  BC, added save for !p.multi so overplot works
           2001 March 7    BC, added centerX/Y, XfillVal, and repaired Yfillval, etc.
           2001 March 16   BC, repaired Yfillval, force all to float/double, added checks for NAN
           2001 March 20   BC, added noYskipGaps, logX, and rearranged calling sequence for clarity
           2001 March 30   BC, added nResCol in place of fixed 2 colors
           2001 April 27   BC, added additional fillValue checks and updated alog10(Z) section
           2001 August 9   BC, added logY tick sections

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/spectrogram.pro)

## SSC_PLOT

[Previous Routine] [Next Routine] [List of Routines]

     NAME: ssc_plot.pro

     PURPOSE: Calls read_myCDF and plotmaster for SSCWEB plots

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/ssc_plot.pro)

## THREE_SIGMA

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Three_sigma
     PURPOSE: For array y, return min and max values within 3 standard
              deviations from the mean
     CALLING SEQUENCE:
           res=three_sigma(y)
     INPUTS:
           y = array of 4 or more elements
     KEYWORD PARAMETERS:
           MODIFIED = use modified sigma which uses kurt. & skew.
                      results in a more liberal acceptance of data
     OUTPUTS:
           structure containing:
           ymin = minimum value within 3 stdev's of mean
           ymax = maximum value within 3 stdev's of mean
     MODIFICATION HISTORY:
       05/2006 This is a function version of the procedure semiminmax.pro
               We've noticed problems when using semiminmax:
               When calling it a second time from within a routine
               the values of ymin,ymax from the first call were passed
               back into semiminmax since now they were existing variables.
               Calling this program as a function solves this problem.

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/three_sigma.pro)

## TIMEAXIS_TEXT

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           TIMEAXIS_text
     PURPOSE:
           Plot a time axis.
     CATEGORY:
     CALLING SEQUENCE:
           timeaxis_text, [t]
     INPUTS:
           t = optional array of seconds after midnight.  in
     KEYWORD PARAMETERS:
           Keywords:
             JD=jd   Set Julian Day number of reference date.
             FORM=f  Set axis label format string, over-rides default.
               do help,dt_tm_mak(/help) to get formats.
               For multi-line labels use @ as line delimiter.
             NTICKS=n  Set approximate number of desired ticks (def=6).
             TITLE=txt Time axis title (def=none).
             TRANGE=[tmin,tmax] Set specified time range.
             YVALUE=Y  Y coordinate of time axis (def=bottom).
             TICKLEN=t Set tick length as % of yrange (def=5).
             /NOLABELS means suppress tick labels.
             /NOYEAR drops year from automatically formatted labels.
               Doesn't apply to user specified formats.
             LABELOFFSET=off Set label Y offset as % yrange (def=0).
               Allows label vertical position adjustment.
             DY=d  Set line spacing factor for multiline labels (def=1).
             COLOR=c   Axis color.
             CHARSIZE=s    Axis text size.
             CHARTHICK=cth thickness of label text (def=1).
             THICK=thk thickness of axes and ticks (def=1).
             MAJOR=g   Linestyle for an optional major tick grid.
             MINOR=g2  Linestyle for an optional minor tick grid.
    	  NOTIME = if set, do not display time label
    	  PLABELOFFSET = offset label by this number of pixels
    		Will supersede 'labeloffset' keyword.
    	  ONLYLABEL = if set, will display label only, no axis, no tick marks.
             AddInfo=addInfor  Array of additional data to be displayed under ticks
             AddFormat=addFormat  Array of format strings for additional data
             AddLabel=addLabel  Array of strings to put in front of first tick info
    	  Add_ds=Add_ds Array of strings to put after the last tick on each line
    	         for
    	  BIGPLOT=bigplot added to allow some special settings for the large CDAWeb
    	  inventory plots.
     OUTPUTS:
     COMMON BLOCKS:
     NOTES:
           Notes: To use do the following:
             plot, t, y, xstyle=4
             timeaxis_text
             If no arguments are given to TIMEAXIS_text then an
             axis will be drawn based on the last plot, if any.
             Try DY=1.5 for PS fonts.
     MODIFICATION HISTORY:
           R. Sterner, 25 Feb, 1991
           R. Sterner, 26 Jun, 1991 --- made nticks=0 give default ticks.
           R. Sterner, 18 Nov, 1991 --- allowed Log Y axes.
           R. Sterner, 11 Dec, 1992 --- added /NOLABELS.
           R. Sterner, 20 May, 1993 --- Made date labeling (jd2mdays).
           Allowed CHARSIZE for SIZE.
           Robert.M.Candey.1@gsfc.nasa.gov, 22 Sept 1993; added addInfo and
              addFormat to put data under the times under the tick marks
           R. Candey, 23 Jun 1995; updated latest version of timeaxis

     Copyright (C) 1991, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/timeaxis_text.pro)

## TIME_INTERVAL

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           TIME_INTERVAL
     PURPOSE:
           Find nice time axis tics. (Based on the routine TNAXES)
     DETAILED DESCRIPTION:
           This routine can be used to find consistent, sensible major (and minor)
           tic positions for a time axis based on the time interval being
           displayed.  It based on the routine TNAXES, but extends it by
           including specific code to handle time intervals of more than
           one day.  I.E. one month, one year, two years, and five years.
           This was specifically designed for the creation of inventory graphs
           but should be generally useful.
     CATEGORY:
     CALLING SEQUENCE:
           TIME_INTERVAL, xmn, xmx, nx, mjx1, mjx2, xinc, [mnx2, mnx2, xinc2]
     INPUTS:
           xmn, xmx = Axis min and max in sec.          in
           nx = Desired number of axis tics.            in
     KEYWORD PARAMETERS:
           Keywords:
             FORM=form  returns a suggested format, suitable
               for use in formatting time axis labels.
               Ex: h$:m$:s$, h$:m$, d$
     OUTPUTS:
           mjx1 = first major tic position in sec.      out
           mjx2 = last major tic position in sec.       out
           xinc = Suggested major tic spacing in sec.   out
           mnx1 = first minor tic position in sec.      out
           mnx2 = last minor tic position in sec.       out
           xinc2 = suggested minor tic spacing in sec.  out
     COMMON BLOCKS:
     NOTES:
     MODIFICATION HISTORY:
           Ron Yurow (March 20, 2019) Original version based on TNAXES.

     Copyright (C) 1988, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/time_interval.pro)

## TNAXES

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           TNAXES
     PURPOSE:
           Find nice time axis tics.
     CATEGORY:
     CALLING SEQUENCE:
           tnaxes, xmn, xmx, nx, mjx1, mjx2, xinc, [mnx2, mnx2, xinc2]
     INPUTS:
           xmn, xmx = Axis min and max in sec.          in
           nx = Desired number of axis tics.            in
     KEYWORD PARAMETERS:
           Keywords:
             FORM=form  returns a suggested format, suitable
               for use in formatting time axis labels.
               Ex: h$:m$:s$, h$:m$, d$
     OUTPUTS:
           mjx1 = first major tic position in sec.      out
           mjx2 = last major tic position in sec.       out
           xinc = Suggested major tic spacing in sec.   out
           mnx1 = first minor tic position in sec.      out
           mnx2 = last minor tic position in sec.       out
           xinc2 = suggested minor tic spacing in sec.  out
     COMMON BLOCKS:
     NOTES:
     MODIFICATION HISTORY:
           R. Sterner. 18 Nov, 1988.
           R. Sterner, 22 Feb, 1991 --- converted to IDL V2.
           R. Sterner, 25 Feb, 1991 --- added minor ticks.
           Johns Hopkins University Applied Physics Laboratory.
    	Robert.M.Candey.1@gsfc.nasa.gov, 21 June 1995, changed default formats

     Copyright (C) 1988, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/TNAXES.pro)

## UNPACK

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           UNPACK
     PURPOSE:
           Uncompress a compressed image
     CATEGORY:

     CALLING SEQUENCE:
           UncompressedImage = UNPACK(CompressedImage)
     INPUTS:
           Image
     KEYWORD PARAMETERS:
           None
     OUTPUTS:
           An uncompressed image
     COMMON BLOCKS:
           COMPRESSION_TABLES
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## VECTPLT

[Previous Routine] [Next Routine] [List of Routines]

     NAME: VECTPLT.PRO

     PURPOSE:  Multi-purpose vector plotting routine for CDF data file
    	    representation

     CALLING SEQUENCE:

       vectplt,mlats,mlons,malts,vest,vnrt,mytimes,qflgs,Stitle=station,$
               mcors=mltin,Qmin=qmin,Qmax=qmax,nopolar=nop,Scale=scale,nobin=nob,$
               p0lat=p0lat,p0lon=p0lon,rot=rot,binlat=bin_lat,binlon=bin_lon,$
               limit=limit,latdel=latdel,londel=londel,Alt=alt,Ttitle=thetitle,$
               lthik=lthik,symsiz=symsiz,symcol=symcol,_extra=extras

     VARIABLES:

     Input:

     mlats(*)    - an N element array of geographic latitudes
     mlons(*)    - an N element array of geographic longitudes
     malts(*)    _ an N element array of geographic altitudes
     vest(*)     - an N element array of the eastward component velocity vector
     vnrt(*)     - an N element array of the northward component velocity vector
     mytimes     - an IDL structure comprised of the following: year, day of year,
    	        month, day of month, and an N element array of seconds of day
     qflgs       - an N element array of the quality flag

     Keyword Parameters:

     Stitle=station  	- Observing Station Name
     mcors=mltin		- Coordinate Transformation Flag
    				0 - Eccentric Dipole Magnetic Local Time
    				1 - Altitude Adjusted Corrected Geomagnetic
    				    Coordinates (AACGC) MLT
    				2 - Geographic Coordinates
     Qmin=qmin		- Minimum exceptable quality flag
     Qmax=qmax		- Maximum exceptable quality flag
     nopolar=nop		- Disables clockdial display; enables user defined
    			  projections
     Scale=scale		- Set the size of vectors plotted (1000 default)
     nobin=nob		- turns off binning and averaging of vectors
     binlat=bin_lat	- latitude bin interval
     binlon=bin_lon	- longitude bin interval
     p0lat=p0lat		- map_set argument; latitude center of map
     p0lon=p0lon		- map_set argument; longitude center of map
     rot=rot		- map_set argument; rotation of map
     limit=limit		- map_set limits
     latdel=latdel		- latitude interval
     londel=londel		- longitude interval
     Alt=alt		- Altitude of coordinate transformation
     Ttitle=thetitle	- Title for plot
     lthik=lthik           - vector line thickness
     symsiz=symsiz         - vector position marker
     symcol=symcol         - vector position marker color

     REQUIRED PROCEDURES:
    	This procedure requires the routine  GENLIB.PRO
           and a shared object module, LIB_PGM.so, of C and fortran source.

(See external/CDAWlib/vectplt.pro)

## VER

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           VER
     PURPOSE:
           Plot a vertical line on a graph at specified x value.
     CATEGORY:
     CALLING SEQUENCE:
           ver, x
     INPUTS:
           x = X value of vertical line. Scalar or array.    in
     KEYWORD PARAMETERS:
           Keywords:
             /DEVICE means work in device coordinates.
             /NORMALIZED means work in normalized coordinates.
               Default is data coordinates.
             LINESTYLE=s.    Linestyle (def=!p.linestyle).
             COLOR=c.        Line Color (def=!p.color).
             THICKNESS=thk   Line thickness (def=!p.thick).
             FILL=clr        Optional color to fill between line pairs.
               Fills between lines 0 and 1, 2 and 3, and so on.
             POINTER=pt      Draw arrowhead pointers at top and bottom
               instead of lines.  Arrowhead dimensions may be given as
               fraction of screen or plot window size, the value of
               pt is height, or [height, width].  For /pointer the
               default used is [.03,.03].
             /BOTTOM  used with POINTER to plot bottom pointers only.
             /TOP  used with POINTER to plot top pointers only.
             /OUT   Keep pointers outside axes (Data coord only).
     OUTPUTS:
     COMMON BLOCKS:
     NOTES:
           Note: see hor.
     MODIFICATION HISTORY:
           R. Sterner, 2 Aug, 1989.
           R. Sterner, 21 May, 1992 --- fixed for log Y axes.
           R. Sterner,  3 Nov, 1992 --- Added /device.
           R. Sterner, 27 Jan, 1993 --- dropped reference to array.
           R. Sterner 20 Jun, 1993 --- added /norm.
           R. Sterner 1994 Feb 2 --- Add THICK.
           R. Sterner, 1994 Jun 3 --- Added FILL.
           R. Sterner, 1994 Jun 16 --- Added POINTER.
           R. Sterner, 1997 Jul 11 --- Added /OUT.

     Copyright (C) 1989, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/ver.pro)

## VIRTUAL_FUNCS[10]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function CONV_POS_HUNGARIAN

     PURPOSE: Convert cl_sp_aux positions x,y,z from GSE to GEI (GCI).
              It could be confusing to the user that the GSE positions
              are given in 'reference s/c position' and 'delta s/c positions'
              while all GEI positions will be their real positions, ie, no
              reference s/c and no deltas.

     INPUT:
        buf           an IDL structure
        org_names     an array of original variables sent to read_myCDF
        index	   variable position in buf

     CALLING SEQUENCE:

             newbuf = conv_pos_hungarian(buf,org_names,index=index)

    unction conv_pos_hungarian, buf, org_names,INDEX=INDEX

    tatus=0
     Establish error handler
    catch, error_status
    if(error_status ne 0) then begin
       print, "ERROR= number: ",error_status," in conv_pos_hungarian.pro"
       print, "ERROR= Message: ",!ERR_STRING
       status = -1
       return, status
    endif
    agnames = tag_names(buf)
    agnames1=tag_names(buf.(index))

     look for the COMPONENT_0 attribute tag for this VV.
    f(tagindex('COMPONENT_0', tagnames1) ge 0) then begin
      component0=buf.(index).COMPONENT_0
      ; Check if the component0 variable exists
      component0_index = tagindex(component0,tagnames)
      ; get coordinates
      handle_value,buf.(component0_index).handle,gse_xyz
    ndif

     look for the COMPONENT_1 attribute tag for this VV.
    f(tagindex('COMPONENT_1', tagnames1) ge 0) then begin
      component1=buf.(index).COMPONENT_1
      component1_index = tagindex(component1,tagnames)
      if (component1_index ne -1) then handle_value,buf.(component1_index).handle,gse_dx_xyz
    ndif

     get time values
    f(tagindex('DEPEND_0', tagnames1) ge 0) then $
      depend0=buf.(index).DEPEND_0
     Check if the depend0 variable exists
    epend0_index = tagindex(depend0,tagnames)
     get time
    andle_value,buf.(depend0_index).handle,depend0

     calculate xyz in gei from gse. Add delta to gse if this is s/c 1,2, or 4
    f (component1_index ne -1) then gse_xyz=gse_xyz+gse_dx_xyz
    ei_xyz=gse_xyz  ; actual values will be replaced

    ear=0 & month=0 & day=0 & hour=0 & minute=0 & sec=0 ; init params for recalc
    or i=0L,n_elements(gei_xyz[0,*])-1 do begin
      recalc,year,day,hour,min,sec,epoch=depend0[i] ; setup conversion values
      ; Create scalar variables required when calling geopack routines
      geigse,xgei,ygei,zgei,gse_xyz[0,i],gse_xyz[1,i],gse_xyz[2,i],-1,depend0[i]
      ;
      gei_xyz[0,i]=xgei
      gei_xyz[1,i]=ygei
      gei_xyz[2,i]=zgei
    ndfor

    uf.(index).handle=handle_create()
    andle_value,buf.(index).handle,gei_xyz,/set

     Check that all variables in the original variable list are declared as
     data otherwise set to support_data
     Find variables w/ var_type == data
    tatus = check_myvartype(buf, org_names)

    eturn, buf

    nd

    Correct FAST DCF By
    UNCTION correct_FAST_By, buf, org_names, INDEX=INDEX, DEBUG=DEBUG

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

      PURPOSE:

     Sign switch is required because Westward component has incorrect
     sign for that portion of the FAST orbit where the spacecraft is
     moving from high to low latitudes.
     For high to low latitude orbits the spin-axis is Westward
     For low to high latitude orbist the spin-axis is Eastward
     Magnetometer data in original key-parameter files appear to be
     in the minus spin-axis direction.
     Algorithm developed by R. J. Strangeway (UCLA), March 27,2012

     CALLING SEQUENCE:

              new_buf = convert_Ni(buf,org_names,index=index)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable
     Constants:

     Keyword Parameters:
     index of variable to populate.

     REQUIRED PROCEDURES:

       none

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[11]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function compute_cadence

     PURPOSE: Determine the resolution between epoch values so that one
     can easily see where the "burst" data is located.  Originally
     implemented for the messenger_mag_rtn dataset.

     INPUT:
        buf           an IDL structure
        org_names     an array of original variables sent to read_myCDF
        index	   variable position in buf

     CALLING SEQUENCE:

             newbuf = compute_cadence(buf,org_names,index=index)

    unction compute_cadence, buf, org_names,INDEX=INDEX

    tatus=0
     Establish error handler
    atch, error_status
    f(error_status ne 0) then begin
      print, "ERROR= number: ",error_status," in compute_cadence"
      print, "ERROR= Message: ",!ERR_STRING
      status = -1
      return, status
    ndif
    agnames = tag_names(buf)
    agnames1=tag_names(buf.(index))

     look for the COMPONENT_0 attribute tag for this VV.
    f(tagindex('COMPONENT_0', tagnames1) ge 0) then begin
      component0=buf.(index).COMPONENT_0
      ; Check if the component0 variable exists
      component0_index = tagindex(component0,tagnames)
      ; get epoch
      handle_value,buf.(component0_index).handle,epoch
    ndif

     calculate the cadence from one epoch to the next.
    um_epochs = n_elements(epoch)

     Modification made by Ron Yurow (11/13/2014)
     Check to make sure that CDF contains at least three records in order to
     correctly compute a cadence.
     Removed by Ron Yurow (11/14/2014)
     So that an actual cadence will be returned no matter how many records are
     the CDF contains.
    if (num_epochs lt 3) then begin
       print, "ERROR= error detected in compute_cadence"
       print, "ERROR= Message: Not enough epoch values to correctly compute cadence values."
       status = -1
       return, status
    endif

    adence = make_array(num_epochs, /double)
     Modification made by Ron Yurow (11/14/2014)
     Added special cases to handle when there are only 1 or 2 epochs in the CDF
     A single epoch will result in a cadence of the FILLVAL
     Two epochs will actually result in reasonable values for cadence.
     I think ....
    ase num_epochs of
    :   cadence [0] = buf.(component0_index).fillval
    :   begin
          cadence[0] = epoch[1]-epoch[0]
          cadence[1] = epoch[1]-epoch[0]
        end
    lse: begin
          cadence[0] = epoch[1]-epoch[0]
          cadence[num_epochs-1] = epoch[num_epochs-1]-epoch[num_epochs-2]

          for i=1L,num_epochs-2 do begin
              if(epoch[i+1]-epoch[i]) < (epoch[i]-epoch[i-1])then $
              cadence[i] = epoch[i+1]-epoch[i] else cadence[i] = epoch[i]-epoch[i-1]
          endfor
        end
    ndcase

    uf.(index).handle=handle_create()
    andle_value,buf.(index).handle,cadence,/set

     Check that all variables in the original variable list are declared as
     data otherwise set to support_data
     Find variables w/ var_type == data
    tatus = check_myvartype(buf, org_names)

    eturn, buf

    nd

    Function: Apply_rtn_qflag
    Purpose: To use the quality variable to "filter out bad messenger
    data points"
    Author: Tami Kovalick, Adnet, May, 2012

    unction apply_rtn_qflag, astruct, orig_names, index=index

    Input: astruct: the structure, created by read_myCDF that should
    		 contain at least one Virtual variable.
    	orig_names: the list of varibles that exist in the structure.
    	index: the virtual variable (index number) for which this function
    		is being called to compute.  If this isn't defined, then
    		the function will find the 1st virtual variable.

    this code assumes that the Component_0 is the "parent" variable,
    Component_1 should be the filter/quality variable.

    astruct will contain all of the variables and metadata necessary
    to filter out the bad flux values (based on the filter variables values -
    a value != 222 or 223.

    tags = tag_names(astruct) ;get the variable names.
    v_tagnames=strarr(1)
    v_tagindx = vv_names(astruct,names=vv_tagnames) ;find the virtual vars

    f keyword_set(index) then begin
     index = index
    ndif else begin ;get the 1st vv

     index = vv_tagindx[0]
     if (vv_tagindx[0] lt 0) then return, -1

    ndelse

    print, 'In Apply_rtn_qflag'
    print, 'Index = ',index
    print, 'Virtual variable ', atags(index)
    print, 'original variables ',orig_names
    help, /struct, astruct
    stop;
    _0 = astruct.(index).COMPONENT_0 ;1st component var (real flux var)

    f (c_0 ne '') then begin ;this should be the real data
     var_idx = tagindex(c_0, atags)
     itags = tag_names(astruct.(var_idx)) ;tags for the real data.

     d = tagindex('DAT',itags)
       if (d[0] ne -1) then  parent_data = astruct.(var_idx).DAT $
       else begin
         d = tagindex('HANDLE',itags)
         handle_value, astruct.(var_idx).HANDLE, parent_data
       endelse
     fill_val = astruct.(var_idx).fillval

    ndif else print, 'Apply_rtn_qflag - parent variable not found'

    ata_size = size(parent_data)

    f (data_size[1] gt 0) then begin

    _0 = astruct.(index).COMPONENT_1 ; should be the quality variable

    f (c_0 ne '') then begin ;
     var_idx = tagindex(c_0, atags)
     itags = tag_names(astruct.(var_idx)) ;tags for the real data.

     d = tagindex('DAT',itags)
       if (d[0] ne -1) then  quality_data = astruct.(var_idx).DAT $
       else begin
         d = tagindex('HANDLE',itags)
         handle_value, astruct.(var_idx).HANDLE, quality_data
       endelse

    ndif else print, 'Quality variable not found'

    help, quality_data
    stop;

    emp = where((quality_data ne 222 and quality_data ne 223), badcnt)
    f (badcnt ge 1) then begin
     print, 'found some bad rtn data, replacing ',badcnt, ' out of ', data_size[1],' values with fill.'
     parent_data[temp] = fill_val
    ndif else begin
     print, 'All ',astruct.(index).COMPONENT_0,' data good'
    ndelse

    now, need to fill the virtual variable data structure with this new data array
    and "turn off" the original variable.

    print, 'badcnt',badcnt
    help, parent_data
    stop;

    emp = handle_create(value=parent_data)

    struct.(index).HANDLE = temp

    arent_data = 1B
    uality_data = 1B

     Check astruct and reset variables not in orignal variable list to metadata,
     so that variables that weren't requested won't be plotted/listed.

      status = check_myvartype(astruct, orig_names)

    eturn, astruct

    ndif else return, -1 ;if there's no rtn B radial/tangent/normal data return -1

    nd

    Function: Apply_rtn_cadence
    Purpose: To use the quality variable to "filter out values
    when the time cadence is less than 200.
    Author: Tami Kovalick, Adnet, May, 2012

    unction apply_rtn_cadence, astruct, orig_names, index=index

    Input: astruct: the structure, created by read_myCDF that should
    		 contain at least one Virtual variable.
    	orig_names: the list of varibles that exist in the structure.
    	index: the virtual variable (index number) for which this function
    		is being called to compute.  If this isn't defined, then
    		the function will find the 1st virtual variable.

    this code assumes that the Component_0 is the "parent" variable,
    Component_1 should be the filter/quality variable.

    astruct will contain all of the variables and metadata necessary
    to filter out the values where the time cadence is less than 200.

    tags = tag_names(astruct) ;get the variable names.
    v_tagnames=strarr(1)
    v_tagindx = vv_names(astruct,names=vv_tagnames) ;find the virtual vars
    f keyword_set(index) then begin
     index = index
    ndif else begin ;get the 1st vv

     index = vv_tagindx[0]
     if (vv_tagindx[0] lt 0) then return, -1

    ndelse

    print, 'In Apply_rtn_cadence'
    print, 'Index = ',index
    print, 'Virtual variable ', atags(index)
    print, 'original variables ',orig_names
    help, /struct, astruct
    stop;
    _0 = astruct.(index).COMPONENT_0 ;1st component var (real variable)

    f (c_0 ne '') then begin ;this should be the real data
     var_idx = tagindex(c_0, atags)
     itags = tag_names(astruct.(var_idx)) ;tags for the real data.

     d = tagindex('DAT',itags)
       if (d[0] ne -1) then  parent_data = astruct.(var_idx).DAT $
       else begin
         d = tagindex('HANDLE',itags)
         if (astruct.(var_idx).HANDLE ne 0) then begin
           handle_value, astruct.(var_idx).HANDLE, parent_data
         endif else begin ;need to call the virtual function to compute the quality variables when they don't exist
             astruct = apply_rtn_qflag(temporary(astruct),orig_names,index=var_idx)
             handle_value, astruct.(var_idx).HANDLE, parent_data
         endelse

       endelse
     fill_val = astruct.(var_idx).fillval

    ndif else print, 'Apply_rtn_cadence - parent variable not found'

    ata_size = size(parent_data)
    ype_code = size(parent_data,/type)

    f (data_size[1] gt 0) then begin

    _0 = astruct.(index).COMPONENT_1 ; should be the time cadence variable

    f (c_0 ne '') then begin ;
     var_idx = tagindex(c_0, atags)
     itags = tag_names(astruct.(var_idx)) ;tags for the real data.

     d = tagindex('DAT',itags)
       if (d[0] ne -1) then  cadence_data = astruct.(var_idx).DAT $
       else begin
         d = tagindex('HANDLE',itags)
         if (astruct.(var_idx).HANDLE ne 0) then begin
           handle_value, astruct.(var_idx).HANDLE, cadence_data
         endif else begin ;need to call the virtual function to compute the epoch_cadence when it doesn't exist yet.
             astruct = compute_cadence(temporary(astruct),orig_names,index=var_idx)
             handle_value, astruct.(var_idx).HANDLE, cadence_data

         endelse
       endelse

    ndif else print, 'Cadence variable not defined'
    emp = where((cadence_data gt 200), tcnt)
    good = data_size[1] - tcnt
    if (tcnt ge 1) then begin
    f (ngood ge 1) then begin
     print, 'removing rtn data gt 200, making a smaller array, original = ',data_size[1],' new size = ', ngood
     new_data = make_array(ngood, type=type_code)
     new_data = parent_data[temp]
    ndif else begin
     new_data = make_array(1, type=type_code)
     new_data[0] = fill_val
     print, 'No cadence <200 data found for ',astruct.(index).COMPONENT_0
    ndelse

    now, need to fill the virtual variable data structure with this new data array
    and "turn off" the original variable.

    print, 'tcnt',tcnt
    help, new_data
    stop;

    emp = handle_create(value=new_data)

    struct.(index).HANDLE = temp
    arent_data = 1B
    adence_data = 1B

     Check astruct and reset variables not in orignal variable list to metadata,
     so that variables that weren't requested won't be plotted/listed.

      status = check_myvartype(astruct, orig_names)

    eturn, astruct

    ndif else return, -1 ;if there's no rtn data return -1

    nd

    The following code was written by Tami Kovalick (ADNET) at GSFC
    Written on 10/21/2019 in order to flatten data stored as 1-d, but the
    the data is meant to be plotted as a time series plot (the associated
    time stamps for the expanded data are in the data cdfs, so
    they don't need to be computed).

    unction flatten_plain, sdata

    data_type = size(sdata, /type)
    data_dims = size(sdata, /dimensions)
    ew_sdata = make_array(sdata_dims[1]*sdata_dims[0], type=sdata_type, value=0)

    lay out the Sdata into one long time series
    compute the new epochs based on the base_epoch plus time_offsets for
    each base

     = 0UL ; counter for the number of elements in the new arrays (needs to be big)
    or i=0,sdata_dims[1]-1 do begin
      for j=0,sdata_dims[0]-1 do begin
          new_sdata[k] = sdata[j,i]
          k = k + 1
      endfor
    ndfor
    eturn, new_sdata
    nd ; flatten_plain

    unction flatten_data_gold, astruct, org_names, INDEX=index, DEBUG=DEBUG

      PURPOSE:

    This routine computes TT2000 epochs from the base times and the
    timeoffsets.  NEED to define the computed epoch variable in the
    master to be of type tt2000.  Also restructures the data from
    size N elements/record out to a single dimensioned array for
    display as a timeseries (where the original/parent data is set
    up for a spectrogram display)

     CALLING SEQUENCE:

              new_buf = flatten_data_gold(buf,org_names, INDEX=INDEX)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable
     Constants:

      none

     Keyword Parameters:
    	INDEX : this can be set the structure variable index # for which
    	you'd like this conversion.  If this isn't set we'll look for the
    	1st variable that's defined as "virtual".

     REQUIRED PROCEDURES:

       none

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[12]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function flatten_data

     PURPOSE: Remove any dimensionality from data array.

     DETAILED DESCRIPTION:

              The flatten_data function removes any dimensionality from the data,
              effectively turning every element into a record with a single value.

     CALLING SEQUENCE:

              new_buf = flatten_data (buf, org_names)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

     History: Written by Ron Yurow 3/3/20, based on alternate_view

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[13]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function make_stack_array

     PURPOSE: take the array of data specified by component_0
     and apply the array reduction specified in the display_type
     place the result in the return buffer.

     CALLING SEQUENCE:

              new_buf = make_stack_array(buf,org_names)

     VARIABLES:

     Input:

      astruct    - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.
      index - keyword - if set use this index value to find the virtual
                        variable, otherwise, find the 1st vv in the structure.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[14]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function fix_sparse

     PURPOSE: take the array of data specified by component_0
     and replace all fill values w/ the preceding non-fill value -
     place the result in the return buffer.

     CALLING SEQUENCE:

              new_buf = fix_sparse(buf,org_names)

     VARIABLES:

     Input:

      astruct    - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.
      index - keyword - if set use this index value to find the virtual
                        variable, otherwise, find the 1st vv in the structure.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[15]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function REORDER_DATA

     PURPOSE: Reorder a variable in monotonic increasing order or based the
              order of a dependent variable(s).

     CALLING SEQUENCE:

              new_buf = reorder (buf, org_names, index)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

     History: Written by Ron Yurow 08/15, based on alternate_view

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[16]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function SPDF_SUM_AVG_OVER_COL_ROW_Z

     PURPOSE: Sum or average a 2d, 3d or 4d array, which is an element of the structure
                returned by spdf_read_data, over the columns, rows, and/or the 3rd dimension
                (here called z for short. Also known as layer, depth, etc)

     PLEASE NOTE: These are consistent with IDL's column-major arrays.
                So if you have a [80, 48, 132] array and you want to average over
                the 1st dimension you will "avg_over_col".

                In addition, for 3d or 4d arrays the last dim is always treated as 'time' in this function
                because that's what's returned by spdf_read_data.

                Finally, I'm adding logic to this function as needed.

     CALLING SEQUENCE EXAMPLES:

              new_buf = spdf_sum_avg_over_col_row_z(buf,org_names,index=vindex,/avg_over_col)
              new_buf = spdf_sum_avg_over_col_row_z(buf,org_names,index=vindex,/sum_col_z)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.
      index      - listed as a keyword but is necessary. Indicates what variable
                   of the input structure we are populating.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters (one of these needs to be selected), all are 1/0 (set/not set):

       2D and 3D arrays can be:
         avg_over_row -
         avg_over_col -
         sum_over_row -
         sum_over_col -

       4D arrays can be:
         avg_col_row -
         avg_col_z -
         avg_row_z -
         sum_col_row -
         sum_col_z -
         sum_row_z -

     REQUIRED PROCEDURES:

       check_myvartype

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[1]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function VTYPE_NAMES

     PURPOSE: Returns array of names or index numbers where the var_type is
              equal to vtype (eg."data").

    unction vtype_names, buf, vtype, NAMES=vNAMES

     tagnames = tag_names(buf)
     tagnums = n_tags(buf)
     vnames=strarr(tagnums)
     vindices=intarr(tagnums)
     Determine names and indices
      ii=0
      for i=0, tagnums-1 do begin
       tagnames1=tag_names(buf.(i))
       if(tagindex('VAR_TYPE', tagnames1) ge 0) then begin
    upcase both sides in case there's mixed case
            if(buf.(i).VAR_TYPE eq vtype) then begin
           if(strupcase(buf.(i).VAR_TYPE) eq strupcase(vtype)) then begin
           ;if(buf.(i).VAR_TYPE eq 'data') then begin
              vnames[ii]=tagnames[i]
              ;vindices(ii)=i
              vindices[ii]=i
              ii=ii+1
           endif
       endif
      endfor

      wc=where(vnames ne '',wcn)
      if(wc[0] lt 0) then begin
       vnames[0]=wc
       vindices[0]=wc
      endif else begin
       vnames=vnames[wc]
       vindices=vindices[wc]
      endelse

    Jan. 6, 2003 - TJK added the "or (n_elements..." below because in IDL 5.6
    if the NAMES keyword is set as "" in the calling routine, IDL doesn't think
    the keyword is set (as it does in previous IDL versions).

    if(keyword_set(NAMES) or (n_elements(names) gt 0)) then begin
    	NAMES=vnames
    endif
    eturn, vindices
    nd

    +

     NAME: Function Trap

     PURPOSE: Trap malformed idl structures or invalid arguments.

     INPUT;  a   an idl structure

    unction buf_trap, a

     ibad=0
     str_tst=size(a)
     if(str_tst[str_tst[0]+1] ne 8) then begin
       ibad=1
       v_data='DATASET=UNDEFINED'
       v_err='ERROR=a'+strtrim(string(i),2)+' not a structure.'
       v_stat='STATUS=Cannot plot this data'
       a=create_struct('DATASET',v_data,'ERROR',v_err,'STATUS',v_stat)
     endif else begin
     Test for errors trapped in conv_map_image
      atags=tag_names(a)
      rflag=tagindex('DATASET',atags)
      if(rflag[0] ne -1) then ibad=1
     endelse

    eturn, ibad
    nd

    +

     NAME: Function VV_NAMES

     PURPOSE: Returns array of virtual variable names or index numbers.

    unction vv_names, buf, NAMES=NAMES

     tagnames = tag_names(buf)
     tagnums = n_tags(buf)
     vnames=strarr(tagnums)
     vindices=intarr(tagnums)
     Determine names and indices
      ii=0
      for i=0, tagnums-1 do begin
       tagnames1=tag_names(buf.(i))
       if(tagindex('VIRTUAL', tagnames1) ge 0) then begin
           if(buf.(i).VIRTUAL) then begin
              vnames[ii]=tagnames[i]
              vindices[ii]=i
              ii=ii+1
           endif
       endif
      endfor
      wc=where(vnames ne '',wcn)
      if(wc[0] lt 0) then begin
       vnames[0]=wc
       vindices[0]=wc
      endif else begin
       vnames=vnames[wc]
       vindices=vindices[wc]
      endelse

    TJK IDL6.1 doesn't recognize this keyword as being set since
    its defined as a strarr(1)...
    if(keyword_set(NAMES)) then NAMES=vnames
    f(n_elements(NAMES)) then begin
    AMES=vnames
    ndif
    eturn, vindices
    nd

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function CHECK_MYVARTYPE

     PURPOSE:
     Check that all variables in the original variable list are declared as
     data otherwise set to ignore_data
     Find variables w/ var_type == data

     CALLING SEQUENCE:

              status = check_myvartype(buf,org_names)

     VARIABLES:

     Input:
      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = metadata.

     Output:
      buf    - an IDL structure containing the populated virtual
                   variables
      status - 0 ok else failed

     Keyword Parameters:

     REQUIRED PROCEDURES:

    unction check_myvartype, nbuf, org_names
      status=0
      var_names=strarr(1)
      var_indices = vtype_names(nbuf,'data',NAMES=var_names)
      if(var_indices[0] lt 0) then begin
        print, "STATUS= No variable of type DATA detected."
        print, "ERROR= No var_type=DATA variable found in check_myvartype.pro"
        print, "ERROR= Message: ",var_indices[0]
        status = -1
        return, status
      endif
      org_names=strupcase(org_names)

      ; RCJ 08/29/2012   Let's find all 'components'. We'll need this list below.
      compnames=['']
      for i=0, n_elements(var_indices)-1 do begin
         tnames=tag_names(nbuf.(i))
         for k=0,n_elements(tnames)-1 do begin
            pos = strpos(tnames[k],'COMPONENT_')
            if (pos eq 0) then compnames=[compnames,nbuf.(var_indices[i]).(k)]
         endfor
      endfor

      for i=0, n_elements(var_indices)-1 do begin
         wc=where(org_names eq var_names[i],wcn)
         if(wc[0] lt 0) then begin  ; this is not the originally requested var.
        ;   print,'***** not requested, make support_data : ',var_names[i]
           nbuf.(var_indices[i]).var_type = 'support_data'
           ;
           wc1=where(strupcase(compnames) eq var_names[i])
           if (wc1[0] ne -1) then nbuf.(var_indices[i]).var_type='additional_data'
       ;    if (wc1[0] ne -1) then print,'********** and a component, make additional_data: ',nbuf.(var_indices[i]).varname
         endif
      endfor
      ;  Old logic: (RCJ 08/29/2012)
      ;
      ; RCJ 01/23/2007  depend_0s is to be used if one of the vars
      ; becomes additional or ignore_data
       depend_0s=''
       for i=0,n_elements(tag_names(nbuf))-1 do begin
          depend_0s=[depend_0s,nbuf.(i).depend_0]
       endfor
       depend_0s=depend_0s[1:*]
       ; RCJ 11/09/2007  Added same thing for depend_1's
       depend_1s=''
       for i=0,n_elements(tag_names(nbuf))-1 do begin
          if (tagindex('DEPEND_1',tag_names(nbuf.(i))) ge 0) then $
          depend_1s=[depend_1s,nbuf.(i).depend_1]
       endfor
       if n_elements(depend_1s) gt 1 then depend_1s=depend_1s[1:*]
      ;
          ; we don't want the var to be ignored in case we are going to write a cdf,
          ; but we also don't want the var listed/plotted, so turn it into a
          ; 'additional_data'.
         ; if ((nbuf.(var_indices(i)).var_type eq 'data') or $
         ;  (nbuf.(var_indices(i)).var_type eq 'support_data')) then $
         ;   nbuf.(var_indices(i)).var_type = 'additional_data' else $
         ;   nbuf.(var_indices(i)).var_type='ignore_data'
         ; if ((nbuf.(var_indices(i)).var_type eq 'additional_data') or $
         ;  (nbuf.(var_indices(i)).var_type eq 'ignore_data')) then begin
         ;	  if nbuf.(var_indices(i)).depend_0 ne '' then begin
         ;       q=where(depend_0s eq nbuf.(var_indices(i)).depend_0)
         ;       if n_elements(q) eq 1 then $
         ;	        s=execute("nbuf."+nbuf.(var_indices(i)).depend_0+".var_type='additional_data'")
         ;    endif
         ;       if nbuf.(var_indices(i)).depend_1 ne '' then begin
         ;       q=where(depend_1s eq nbuf.(var_indices(i)).depend_1)
         ;       if n_elements(q) eq 1 then $
         ;	        s=execute("nbuf."+nbuf.(var_indices(i)).depend_1+".var_type='additional_data'")
         ;    endif
         ; endif
          ; RCJ 07/14/2008  Now we do want the depends listed.
           print,'*********** not requested: ', nbuf.(var_indices[i]).varname,'  ',nbuf.(var_indices[i]).var_type
           if (nbuf.(var_indices[i]).var_type eq 'data')  then $
             nbuf.(var_indices[i]).var_type='additional_data'
           if (nbuf.(var_indices[i]).var_type eq 'additional_data') then begin
          	  if nbuf.(var_indices[i]).depend_0 ne '' then begin
                       q=where(depend_0s eq nbuf.(var_indices[i]).depend_0)
                       if n_elements(q) eq 1 then $
          	        s=execute("nbuf."+nbuf.(var_indices[i]).depend_0+".var_type='additional_data'")
                    endif
          	  if nbuf.(var_indices[i]).depend_1 ne '' then begin
                       q=where(depend_1s eq nbuf.(var_indices[i]).depend_1)
                       if n_elements(q) eq 1 then $
          	        s=execute("nbuf."+nbuf.(var_indices[i]).depend_1+".var_type='additional_data'")
              endif
          endif

        Even older logic:  (RCJ 08/29/2012)

       ;if(wc[0] lt 0) then nbuf.(var_indices[i]).var_type="ignore_data"
       ;if(wc[0] lt 0) then nbuf.(var_indices[i]).var_type="metadata"

    eturn, status
    nd

    +
     NAME: Function ALTERNATE_VIEW

     PURPOSE: Find virtual variables and replace their data w/ the component0
              data

     CALLING SEQUENCE:

              new_buf = alternate_view(buf,org_names)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function CLAMP_TO_ZERO

     PURPOSE: Clamp all values less than or equal to 'clamp_threshold' to zero.

     CALLING SEQUENCE:

              new_buf = clamp_to_zero(buf,org_names)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

     History: Written by Ron Yurow 08/15, based on alternate_view

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[3]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function COMPOSITE_TBL

     PURPOSE: Create a variable that is a composite of of multiple variables.

     CALLING SEQUENCE:

              new_buf = composite_tbl(buf,org_names)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

     History: Written by Ron Yurow 08/15, based on alternate_view

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[4]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function arr_slice

     PURPOSE: Create a variable by extracting a subset (slice) of a multidimensional array.
              Works on variables up to 7 dimensions.

     DETAILED DESCRIPTION:

              The arr_slice virtual function extracts a subarray of a multidimensional
              variable, in the processes reducing the dimensionality of the resultant
              data array by 1.  The dimensionality of the original data variable must be
              at least 2.

              The arr_slice function requires that COMPONENT_0 vAttribute be set to source
              data variable.  In addition, the following vAttributes are also required:

              ARR_INDEX:    Index into the requested dimension to extract the subarray from.
              ARR_DIM:      The dimension of the source data variable to reduce.

              All values are referenced from 0.

              As an example suppose the variable TEST is a 10 x 10 Array.  Specifying an
              ARR_INDEX of 4 and an ARR_DIM of 0 would result in a vector consisting of the
              5th column of the array.  Likewise, specifying and ARR_INDEX of 0 and an
              ARR_DIM of 1 would result in a vector consisting of the 1st row of the array.

              The master fa_esa_l2_ies_00000000_v01 has been updated so that the variables
              "pitch_angle_median" and "energy_median" now use this function.

     CALLING SEQUENCE:

              new_buf = arr_slice (buf,org_names)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

     History: Written by Ron Yurow 05/16, based on alternate_view

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[5]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function CROP_IMAGE

     PURPOSE: Crop [60,20,*] images into [20,20,*]

     CALLING SEQUENCE:

              new_buf = crop_image(buf,org_names,index)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.
      index      - variable index, so we deal with one variable at a time.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     History: Written by RCJ 12/00, based on alternate_view

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[6]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function clean_data

     pURPOSE: Remove data 3*sigma from mean

     INPUT:

        data          simple data array

     KEYWORDS:
        FILLVAL       the fill value to be used to replace outlying data.

     CALLING SEQUENCE:

             data = clean_data(data,keywords...)

    unction clean_data, data, FILLVAL=FILLVAL

    if not keyword_set(FILLVAL) then FILLVAL=1.0+e31;

      w=where(data ne FILLVAL,wn)
      if(wn eq 0) then begin
        print, "ERROR = No valid data found in function clean_data";
        print, "STATUS = No valid data found. Re-select time interval.";
      endif

       mean= total(data[w[0:(wn-1)]])/fix(wn)
      ; RCJ 10/03/2003 The function moment needs data to have 2 or more elements.
      ; If that's not possible, then the mean will be the only valid element of
      ; data and the sdev will be 0.

      if n_elements(data[w[0:(wn-1)]]) gt 1 then begin
         result = moment(data[w[0:(wn-1)]],sdev=sig)
         mean=result[0]
      endif else begin
         mean=data[w[0:(wn-1)]]
         sig=0.
      endelse
      sig3=3.0*sig

      w=where(abs(data-mean) gt sig3, wn);
    TJK 4/8/2005 - add the next two lines because we have a case where
     all of the data values are exactly the same, and the "moment" routine
     above returns a sig value greater that the difference between the mean
     and data, so all values are set to fill, which isn't correct at all...
     So to make up for this apparent bug in the moment routine, do the following:

      t = where(data eq data[0], tn)
      if (tn eq n_elements(data)) then begin
    wn = 0
    print, 'DEBUG clean_data - overriding results from moment func. because '
    print, 'all data are the same valid value = ',data[0]
      endif

      if(wn gt 0) then data[w] = FILLVAL

    eturn, data
    nd

    +
     NAME: Function CONV_POS

     PURPOSE: Find virtual variables and compute their data w/ the component0,
              component1,... data.  This function specifically converts position
              information from 1 coordinate system into another.

     INPUT:

        buf           an IDL structure
        org_names     an array of original variables sent to read_myCDF

     KEYWORDS:
        COORD         string corresponding to coordinate transformation
    	           default(SYN-GCI)
    	           (ANG-GSE)
        TSTART        start time for synthetic data
        TSTOP         start time for synthetic data

     CALLING SEQUENCE:

             newbuf = conv_pos(buf,org_names,keywords...)

    unction conv_pos, buf, org_names, COORD=COORD, TSTART=TSTART, $
                      TSTOP=TSTOP, DEBUG=DEBUG, INDEX=INDEX

    status=0
     Establish error handler
    catch, error_status
    if(error_status ne 0) then begin
      print, "ERROR= number: ",error_status," in conv_pos.pro"
      print, "ERROR= Message: ",!ERR_STRING
      status = -1
      return, status
    endif

    org_names=strupcase(org_names)
    if keyword_set(DEBUG) then DEBUG=1L else DEBUG=0L
    if not keyword_set(INDEX) then INDEX=0L;
    if not keyword_set(COORD) then COORD="SYN-GCI";
    if (keyword_set(TSTART) and keyword_set(TSTOP))then begin
           start_time = 0.0D0 ; initialize
           b = size(TSTART) & c = n_elements(b)
           if (b[c-2] eq 5) then start_time = TSTART $ ; double float already
           else if (b[c-2] eq 7) then start_time = encode_cdfepoch(TSTART); string
           stop_time = 0.0D0 ; initialize
           b = size(TSTOP) & c = n_elements(b)
           if (b[c-2] eq 5) then stop_time = TSTOP $ ; double float already
           else if (b[c-2] eq 7) then stop_time = encode_cdfepoch(TSTOP); string
    endif

    ;m3int=fix((stop_time - start_time)/(180.0*1000.0))
    ; RCJ 07/10/02 Replaced fix w/ round. Fix won't work correctly on long integers
    m3int=round((stop_time - start_time)/(180.0*1000.0))
    t3min=dblarr(m3int+1)
    failed=0

    dep=parse_mydepend0(buf)
    depends=tag_names(dep)
    depend0=depends[dep.num]
    epoch1='Epoch1'
    namest=strupcase(tag_names(buf))

    if((COORD eq "SYN-GCI") or (COORD eq "SYN-GEO")) then begin
     Determine time array
    depend0=strupcase(buf.(INDEX).depend_0)
    incep=where(namest eq depend0,w)
    incep=incep[0]
    names=tag_names(buf.(incep))
    ntags=n_tags(buf.(incep))
     Check to see if HANDLE a tag name
    wh=where(names eq 'HANDLE',whn)
    if(whn) then begin
     handle_value, buf.(incep).HANDLE,time
     datsz=size(time)
    endif else begin
     time=buf.(incep).dat
    endelse
     Determine position array
    help, buf.sc_pos_syngci, /struct
     vvtag_names=strarr(1)
     vvtag_indices = vv_names(buf,NAMES=vvtag_names)
     vvtag_names = strupcase(vvtag_names)

    TJK 12/15/2006, the following doesn't work when reading a
    a1_k0_mpa data file directly (w/o a master) because
    the data cdfs have one of the label variables incorrectly
    defined as a virtual variable, so you can't just assume
    the 1st one in vvtag_indices is the correct one.
     use the index passed in instead of vvtag_indices[0]
      cond0=buf.(vvtag_indices[0]).COMPONENT_0
     cond0=buf.(index).COMPONENT_0
     x0=execute('handle_value, buf.'+cond0+'.HANDLE,data')
    TJK 12/15/2006 these aren't right either - we'll use index
      fillval=buf.(vvtag_indices[0]).fillval
      rmin=buf.(vvtag_indices[0]).VALIDMIN[0]
      tmin=buf.(vvtag_indices[0]).VALIDMIN[1]
      pmin=buf.(vvtag_indices[0]).VALIDMIN[2]
      rmax=buf.(vvtag_indices[0]).VALIDMAX[0]
      tmax=buf.(vvtag_indices[0]).VALIDMAX[1]
      pmax=buf.(vvtag_indices[0]).VALIDMAX[2]
     fillval=buf.(index).fillval
     rmin=buf.(index).VALIDMIN[0]
     tmin=buf.(index).VALIDMIN[1]
     pmin=buf.(index).VALIDMIN[2]
     rmax=buf.(index).VALIDMAX[0]
     tmax=buf.(index).VALIDMAX[1]
     pmax=buf.(index).VALIDMAX[2]

      x0=execute('cond0=buf.'+vvtag_indices[0]+'.COMPONENT_0')
      x0=execute('handle_value, buf.'+org_names[0]+'.HANDLE,data')
      x0=execute('fillval=buf.'+org_names[0]+'.fillval')

     if(COORD eq "SYN-GCI") then begin
     r=data[0,*]
     theta=data[1,*]
     phi=data[2,*]
     Check for radius in kilometers; switch to Re
     wrr=where(((r gt 36000.0) and (r lt 48000.0)),wrrn)
     if(wrrn gt 0) then r[wrr] = r[wrr]/6371.2

     Check validity of data; if outside min and max set to fill
     rhi=where(r gt rmax,rhin)
     if(rhin gt 0) then r[rhi]=fillval
     rlo=where(r lt rmin,rlon)
     if(rlon gt 0) then r[rlo]=fillval
     ;print, rmax, rmin
     ;print, 'DEBUG',min(r, max=maxr) & print, maxr

     thi=where(theta gt tmax,thin)
     if(thin gt 0) then theta[thi]=fillval
     tlo=where(theta lt tmin,tlon)
     if(tlon gt 0) then theta[tlo]=fillval

     phii=where(phi gt pmax,phin)
     if(phin gt 0) then phi[phii]=fillval
     plo=where(phi lt pmin,plon)
     if(plon gt 0) then phi[plo]=fillval

     num=long(n_elements(time))
     stime=time-time[0]
     dtime=(time[num-1] - time[0])/1000.0
     d_m3time=dtime/(60.0*3.0)  ; 3min/interval=(secs/interval) / (secs/3min)
     m3time=fix(d_m3time)

     Compute syn_phi, syn_r, and syn_theta
      syn_phi=dblarr(m3int+1)
      syn_theta=dblarr(m3int+1)
      syn_r=dblarr(m3int+1)
      newtime=dblarr(m3int+1)
      tst_theta=dblarr(num)

     Clean up any bad data; set to fill values outside 3-sigma
      phi=clean_data(phi,FILLVAL=fillval)
      theta=clean_data(theta,FILLVAL=fillval)
      r=clean_data(r,FILLVAL=fillval)

      wcp=where(phi ne fillval,wcnp)
      wct=where(theta ne fillval,wcnt)
      wcr=where(r ne fillval,wcnr)
      if((wcnp le 0) or (wcnt le 0) or (wcnr le 0)) then begin
        print, 'ERROR= Data all fill'
        print, 'STATUS= No valid data found for this time period'
        return, -1
      endif
      if((wcnp eq 1) or (wcnt eq 1) or (wcnr eq 1)) then begin
        print, 'ERROR= Only one valid point'
        print, 'STATUS= Only one valid point found for this time period'
        return, -1
      endif
     For short intervals < 10 points use wcnp otherwise average the 1st 10 points
     to obtain extrapolation parameters
      ;wcnp=wcnp-1
      ;if(wcnp gt 10) then wcnp=10 else wcnp=wcnp-1
     Compute average of all points
      mphi= total(phi[wcp[0:(wcnp-1)]])/fix(wcnp)
      ;mr= total(r(wcr[0:(wcnr-1)]))/fix(wcnr)
      mr= total(r[wcr[0:(wcnr-1)]])/fix(wcnr)
      mtheta= total(theta[wct[0:(wcnt-1)]])/fix(wcnt)
      ampl=double(max(theta[wct]))
    print, mphi, mr, mtheta, ampl
      wc=where(theta eq ampl,wcn)

     dphi=phi[wcp[wcnp-1]] - phi[wcp[0]]
     dr=r[wcr[wcnr-1]] - r[wcr[0]]
     dtheta=theta[wct[wcnt-1]] - theta[wct[0]]
     phi_rate=dphi/d_m3time
     r_rate=dr/d_m3time
     theta_rate=dtheta/d_m3time
     nominal_rate=0.75
     new_rate= double(360.0/(nominal_rate + phi_rate))
      print, nominal_rate, phi_rate, new_rate, r_rate

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     Skip latitude daily variation approximation
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      iter=0
      sign=0
      corr_coef=0.0
      while(corr_coef lt 0.75) do begin
       T=time(wc[0])/180000.0
    ;   T1=time(wc[0]-1)/180000.0
    ;   T2=time(wc[0]-2)/180000.0
    ;   T3=time(wc[0]+1)/180000.0
    ;   T4=time(wc[0]+2)/180000.0
       if(iter eq 0) then T=double(T)
    ;   if(iter eq 1) then T=double((T+T1)/2.0)
    ;   if(iter eq 2) then T=double((T1+T2)/2.0)
    ;   if(iter eq 3) then T=double((T+T3)/2.0)
    ;   if(iter eq 4) then T=double((T4+T3)/2.0)
    ;print, ampl,  T, mphi, mr, mtheta

    ; determine array for correlation test
       for i=0L,num-1 do begin
          tm=time[i]/(180.0*1000.0)
    ;     tst_theta[i] = ampl*sin((2.0*(!pi))*(tm-T)/480.08898)
          if(sign eq 0) then tst_theta[i] = ampl*double(cos((2.0*(!pi))*(tm-T)/new_rate))
          if(sign eq 1) then tst_theta[i] = ampl*double(sin((2.0*(!pi))*(tm-T)/new_rate))
       endfor

       corr_coef=correlate(theta,tst_theta)
       if(DEBUG) then print, iter," CC = ", corr_coef

    ;   if(iter eq 4) then begin
         if(sign eq 0) then begin
            iter=0
            sign = 1
         endif
    ;   endif
       iter=iter+1
    ;   if(iter gt 5) then goto, break
       if(iter gt 1) then goto, break
      endwhile
      break:

       if(corr_coef lt 0.75) then failed=1

     failed=1  ; forces average theta variation to be used approx. 0.0
     Generate 3-min data
      for i=0L,m3int do begin
       tm = (start_time)/180000.0 + i
       t3min[i]=i*180000.0 + start_time
       half=m3int/2
       it=i-(half+1)
       syn_phi[i] = mphi + phi_rate*it
       ; syn_r[i] = mr + r_rate*i
       syn_r[i] = mr
      if(failed) then begin
        if(abs(mtheta) > 2.0) then begin
          print, 'WARNING: Check daily latitude variation.'
          return, -1;
        endif
         syn_theta[i] = 0.0  ; Can't compute daily variation; use this estimate
       ; syn_theta[i] = mtheta ; Can't compute daily variation; use this estimate
       ; syn_theta[i] = mtheta + theta_rate*i
      endif else begin
         syn_theta[i] = ampl*sin((2.0*(!pi))*(tm-T)/480.08898)
       if(sign eq 0) then syn_theta[i] = ampl*double(cos((2.0*(!pi))*(tm-T)/new_rate))
       if(sign eq 1) then syn_theta[i] = ampl*double(sin((2.0*(!pi))*(tm-T)/new_rate))
      endelse
     endfor

          print, t3min[0], syn_r[0], syn_theta[0], syn_phi[0]
     Convert spherical to cartesian
        Determine the offset of the given point from the origin.
     gei=dblarr(3,m3int+1)
     geo=dblarr(3,m3int+1)
     deg2rd=!pi/180.0
     j=-1
     for i=0L, m3int do begin
         CT = SIN(syn_theta[i]*deg2rd)
         ST = COS(syn_theta[i]*deg2rd)
         CP = COS(syn_phi[i]*deg2rd)
         SP = SIN(syn_phi[i]*deg2rd)
     Save syn-geo
          geo[0,i]=syn_r[i]
          geo[1,i]=syn_theta[i]
          geo[2,i]=syn_phi[i]
         Convert GEO spherical coordinates SGEO(1,2,3) [R,LAT,LON]
              to GEO cartesian coordinates in REs GEO(1,2,3) [X,Y,Z].
         RHO =    syn_r[i] * ST
         xgeo = RHO * CP
         ygeo = RHO * SP
         zgeo = syn_r[i] * CT
         xgei=0.0 & ygei=0.0 & zgei=0.0
     Rotate 3-min vectors from geo to gci
         epoch=t3min[i]
          cdf_epoch, epoch, yr, mo, dy, hr, mn, sc, milli, /break
          if((i mod 100) eq 0) then print, epoch, yr, mo, dy, hr, mn, sc, milli
         geigeo,xgei,ygei,zgei,xgeo,ygeo,zgeo,j,epoch=epoch
           if((i mod 100) eq 0) then print, xgei,ygei,zgei,xgeo,ygeo,zgeo
          gei[0,i]=xgei
          gei[1,i]=ygei
          gei[2,i]=zgei
     endfor

     Modify existing structure

     nbuf=buf
     Modify depend0 (Epoch1), but don't add it again!!
     dc=where(depends eq 'EPOCH1',dcn)
     if(not dcn) then begin
      nu_ep_handle=handle_create(value=t3min)
      ;x0=execute('nbuf.'+depend0+'.handle=nu_ep_handle')
      x0=execute('temp_buf=nbuf.'+depend0)
      new=create_struct('EPOCH1',temp_buf)
      x0=execute('new.'+epoch1+'.handle=nu_ep_handle')
      x0=execute('new.'+epoch1+'.VARNAME=epoch1')
      x0=execute('new.'+epoch1+'.LABLAXIS=epoch1')
     endif
     Modify position data
     if(COORD eq "SYN-GCI") then begin
       nu_dat_handle=handle_create(value=gei)
       vin=where(vvtag_names eq 'SC_POS_SYNGCI',vinn)
       if(vinn) then begin
         ;nbuf.(vvtag_indices(vin[0])).handle=nu_dat_handle
         nbuf.(vvtag_indices[vin[0]]).handle=nu_dat_handle
         ;nbuf.(vvtag_indices(vin[0])).depend_0=epoch1
         nbuf.(vvtag_indices[vin[0]]).depend_0=epoch1
       endif
     endif
     if(COORD eq "SYN-GEO") then begin
       nu_dat_handle=handle_create(value=geo)
       vin=where(vvtag_names eq 'SC_POS_SYNGEO',vinn)
       if(vinn) then begin
         ;nbuf.(vvtag_indices(vin[0])).handle=nu_dat_handle
         nbuf.(vvtag_indices[vin[0]]).handle=nu_dat_handle
         ;nbuf.(vvtag_indices(vin[0])).depend_0=epoch1
         nbuf.(vvtag_indices[vin[0]]).depend_0=epoch1
       endif
     endif

     cond0=strupcase(cond0)
     pc=where(org_names eq cond0,pcn)
     ;blank=' '
     if(pc[0] eq -1) then begin
       ; RCJ 06/16/2004  Only make epoch.var_type = metadata if no other
       ; variable needs epoch as its depend_0. in this case epoch
       ; should still be support_data.
       q=where(strlowcase(depends) eq 'epoch')
       if q[0] eq -1 then nbuf.epoch.var_type='metadata'
       ; RCJ 01/23/2007 The line below does not help listing. Does it do anything useful?
       ;nbuf.sc_pos_geo.depend_0=blank
     endif

     if(not dcn) then nbuf=create_struct(nbuf,new)
    endif

    if(COORD eq "ANG-GSE") then begin
     nbuf=buf
     vvtag_names=strarr(1)
     vvtag_indices = vv_names(buf,NAMES=vvtag_names)

     Determine time array
     depend0=depends(INDEX)
     incep=where(vvtag_names eq namest(INDEX),w)
     incep=incep[0]
    ;depend0=buf.(vvtag_indices(incep)).DEPEND_0
    depend0=buf.(INDEX).DEPEND_0
    print, depend0, INDEX
    incep=tagindex(depend0, namest)
    incep=incep[0]
    names=tag_names(buf.(incep))
    ntags=n_tags(buf.(incep))
     Check to see if HANDLE a tag name
    wh=where(names eq 'HANDLE',whn)
    if(whn) then begin
     handle_value, buf.(incep).HANDLE,time
     datsz=size(time)
    endif else begin
     time=buf.(incep).dat
    endelse
     Determine position array
      indat=where(vvtag_names eq namest(INDEX),w)
      indat = indat[0]
     cond0=buf.(INDEX).COMPONENT_0
     ;cond0=buf.(vvtag_indices(indat)).COMPONENT_0
    print, cond0, INDEX
     x0=execute('handle_value, buf.'+cond0+'.HANDLE,data')

     Convert BGSE vector to angular BGSE;
     data_sz=size(data)
     ang_gse=dblarr(data_sz[1],data_sz[2])
      cart_polar,data[0,*],data[1,*],data[2,*],ang_gse[0,*],ang_gse[1,*],$
                 ang_gse[2,*],1,/degrees
     ang_gse[0,*]=sqrt(data[0,*]*data[0,*]+data[1,*]*data[1,*]+data[2,*]*data[2,*])
     ang_gse[0,*]=sqrt(data[0,*]^2+data[1,*]^2+data[2,*]^2)
     ang_gse[1,*]=90.0-(!radeg*acos(data[2,*]/ang_gse[0,*]))
     ang_gse[2,*]=!radeg*atan(data[1,*],data[0,*])
     wc=where(ang_gse[2,*] lt 0.0,wcn)
     if(wcn gt 0) then ang_gse[2,wc] = ang_gse[2,wc]+360.0
     nu_dat_handle=handle_create(value=ang_gse)
     ;nbuf.(vvtag_indices(indat)).handle=nu_dat_handle
     nbuf.(INDEX).handle=nu_dat_handle
    endif

     Check that all variables in the original variable list are declared as
     data otherwise set to metadata
     Find variables w/ var_type == data

      status = check_myvartype(nbuf, org_names)

    eturn, nbuf
    nd

    to get help: IDL> ptg,/help
     ancillary routines --------------------------------------------

    UNCTION dtand,x
       RETURN,DOUBLE(TAN(x*!DTOR))
    ND

    UNCTION datand,x
       RETURN,DOUBLE(ATAN(x)/!DTOR)
    ND

    UNCTION fgeodeP,a,b,v1x,v1y,v1z,v2x,v2y,v2z
       RETURN,v1x*v2x + v1y*v2y + v1z*v2z * a*a/(b*b)
    ND

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[7]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function CONV_MAP_IMAGE

     PURPOSE: Convert provided idl structure to structure containing neccesary
              variables for an auroral image map.  Use variables pointed to by
              COMPONENT variable attributes to compute geodetic latitude and
              longitude. Populate GEOD_LAT & GEOD_LONG variables w/ the computed
              values. Return the modifiy idl structure.

      NEED TO REMOVE UVI DEPENDENCIES.......

     CALLING SEQUENCE:

              new_buf = conv_map_image(buf,org_names)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     Keyword Parameters:

     REQUIRED PROCEDURES:

       none

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[8]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function HEIGHT_ISIS

     PURPOSE: Retrieve only height from vector geo_coord:
     (lat1, lon1, height1, lat2, lon2, height2, lat3, lon3, height3, .....)

     CALLING SEQUENCE:

              new_buf = height_isis(buf,org_names,index)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.
      index      - variable index, so we deal with one variable at a time.

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     History: Written by RCJ 09/01, based on crop_image

(See external/CDAWlib/virtual_funcs.pro)

## VIRTUAL_FUNCS[9]

[Previous Routine] [Next Routine] [List of Routines]

     NAME: Function FLIP_IMAGE

     PURPOSE: Flip_image [*,*]

     CALLING SEQUENCE:

              new_buf = flip_image(buf,org_names,index)

     VARIABLES:

     Input:

      buf        - an IDL structure built w/in read_myCDF
      org_names  - list of original variables input to read_myCDF. Any
                   variables in this list will remain tagged as
                   VAR_TYPE= data otherwise VAR_TYPE = support_data.
      index      - variable index, so we deal with one variable at a time.
      direction  - IDL's 'rotate' input to determine which rotation and 'flip' to apply

     Output:

      new_buf    - an IDL structure containing the populated virtual
                   variable

     History: Written by TJK 01/03 for use w/ IDL RPI data
              RCJ 29May2020  Added keyword direction to be able to use
                             options from idl's 'rotate'

(See external/CDAWlib/virtual_funcs.pro)

## VIS-CAL

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           VIS-CAL

     PURPOSE:
      This is the main procedure for processing Polar VIS data

     CALLING SEQUENCE:
      VIS-CAL

     INPUTS:
      None

     KEYWORD PARAMETERS:

     OUTPUTS:
      None

     COMMON BLOCKS:

     MODIFICATION HISTORY:
           Written by:     Ron Yurow 04/15/2015
           Based on code written for XVIS

(See external/CDAWlib/viscal.pro)

## VISCAL[1]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:     GCI_TO_GEO

     PURPOSE:
           Converts a GCI coordinate into geographic lat,lon,alt (alt=altitude)
     CATEGORY:

     CALLING SEQUENCE:
           GCI_TO_GEO, Pos, gla, glo, alt
     INPUTS:
           POS == a position in GCI coordinates
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           GLA == geographic latitude
           GLO == geographic longitude
           ALT == altitude
     COMMON BLOCKS:
           XV_RECORD_DATA
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## VISCAL[2]

[Previous Routine] [Next Routine] [List of Routines]

     Bobby may not need

(See external/CDAWlib/viscal.pro)

## VISCAL[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:      SINGLE_PIXEL_CRD

     PURPOSE:
           Computes coordinates for one image pixel location
     CATEGORY:

     CALLING SEQUENCE:
           coord = SINGLE_PIXEL_CRD( X, Y, ON_EARTH )
     INPUTS:
           X,Y == pixel location column and row
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           If look direction at input pixel location intersects Earth,
           GCI coordinates of position on surface of Earth closer to spacecraft;
           else GCI unit vector for look direction

           ON_EARTH == number of points of intersection with Earth, 0, 1, or 2

     COMMON BLOCKS:
           XV_FILE_DATA
           XV_RECORD_DATA
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97
    	Rae Dvorsky, 3/19/05  to call make_rotation_matrix
    		     NOV 2012 to call vpoint instead of point

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## WRITE_MGIF

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
    	WRITE_MGIF

     PURPOSE:
    	Write an IDL image and color table vectors to a
    	GIF (graphics interchange format) file.

     CATEGORY:

     CALLING SEQUENCE:

     INPUTS:
    	Image:	The 2D array to be output.

     OPTIONAL INPUT PARAMETERS:
          R, G, B:	The Red, Green, and Blue color vectors to be written
    		with Image.
     Keyword Inputs:
    	CLOSE = if set, closes any open file if the MULTIPLE images
    		per file mode was used.  If this keyword is present,
    		nothing is written, and all other parameters are ignored.

     OUTPUTS:
    	Writes files containing multiple images.
    	Each call to WRITE_GIF writes the next image,
    	with the file remaining open between calls.  The File
    	parameter is ignored, but must be supplied,
    	after the first call.  When writing
    	the 2nd and subsequent images, R, G, and B are ignored.
    	All images written to a file must be the same size.

    	If R, G, B values are not provided, the last color table
    	established using LOADCT is saved. The table is padded to
    	256 entries. If LOADCT has never been called, we call it with
    	the gray scale entry.

     COMMON BLOCKS:
    	COLORS

     SIDE EFFECTS:
    	If R, G, and B aren't supplied and LOADCT hasn't been called yet,
    	this routine uses LOADCT to load the B/W tables.

     COMMON BLOCKS:
    	WRITE_GIF_COMMON.

     RESTRICTIONS:
    	This routine only writes 8-bit deep GIF files of the standard
    	type: (non-interlaced, global colormap, 1 image, no local colormap)

    	The Graphics Interchange Format(c) is the Copyright property
    	of CompuServ Incorporated.  GIF(sm) is a Service Mark property of
    	CompuServ Incorporated.

     MODIFICATION HISTORY:
    	Written 9 June 1992, JWG.
    	Added MULTIPLE and CLOSE, Aug, 1996.

       Updated 9 December 1999, Eduardo Iturrate
       If MULTIPLE GIF is created, it will loop 65535 times
         (the available maximum).

(See external/CDAWlib/write_mgif.pro)

## XDISPLAYFILE

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
    	XDISPLAYFILE

     PURPOSE:
    	Display an ASCII text file using widgets and the widget manager.

     CATEGORY:
    	Widgets.

     CALLING SEQUENCE:
    	XDISPLAYFILE, Filename

     INPUTS:
         Filename:	A scalar string that contains the filename of the file
    		to display.  The filename can include a path to that file.

     KEYWORD PARAMETERS:
    	BLOCK:  Set this keyword to have XMANAGER block when this
    		application is registered.  By default the Xmanager
                   keyword NO_BLOCK is set to 1 to provide access to the
                   command line if active command 	line processing is available.
                   Note that setting BLOCK for this application will cause
    		all widget applications to block, not only this
    		application.  For more information see the NO_BLOCK keyword
    		to XMANAGER.

    	DONE_BUTTON: the text to use for the Done button.  If omitted,
    		the text "Done with <filename>" is used.

    	EDITABLE: Set this keyword to allow modifications to the text
    		displayed in XDISPLAYFILE.  Setting this keyword also
    		adds a "Save" button in addition to the Done button.

    	FONT:   The name of the font to use.  If omitted use the default
    		font.
    	GROUP:	The widget ID of the group leader of the widget.  If this
    		keyword is specified, the death of the group leader results in
    		the death of XDISPLAYFILE.

           GROW_TO_SCREEN: If TRUE, the length of the display area is grown
    		to show as much of the text as possible without being too
    		large to fit on the screen. In this case, HEIGHT sets the
    		lower bound on the size instead of setting the size itself.

    	HEIGHT:	The number of text lines that the widget should display at one
    		time.  If this keyword is not specified, 24 lines is the
    		default.

           RETURN_ID : A variable to be set to the widget ID of the top level
                   base of the resulting help application.
    	TEXT:	A string or string array to be displayed in the widget
    		instead of the contents of a file.  This keyword supercedes
    		the FILENAME input parameter.

    	TITLE:	A string to use as the widget title rather than the file name
    		or "XDisplayFile".

    	WIDTH:	The number of characters wide the widget should be.  If this
    		keyword is not specified, 80 characters is the default.

    	WTEXT:	Output parameter, the id of the text widget.  This allows
    		setting text selections and cursor positions programmatically.

     OUTPUTS:
    	No explicit outputs.  A file viewing widget is created.

     SIDE EFFECTS:
    	Triggers the XMANAGER if it is not already in use.

     RESTRICTIONS:
    	None.

     PROCEDURE:
    	Open a file and create a widget to display its contents.

     MODIFICATION HISTORY:
    	Written By Steve Richards, December 1990
    	Graceful error recovery, DMS, Feb, 1992.
           12 Jan. 1994  - KDB
                   If file was empty, program would crash. Fixed.
           4 Oct. 1994     MLR Fixed bug if /TEXT was present and /TITLE was not.
    	2 jan 1997	DMS Added DONE_BUTTON keyword, made Done
    			button align on left, removed padding.
    	19 Nov 2004, GROW_TO_SCREEN and RETURN_ID keywords. Allow for
                           user to resize display. General updating.

(See external/CDAWlib/cdaweb_xdisplayfile.pro)

## XV_GET_ALTLS

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           XV_GET_ALTLS
     PURPOSE:
           Computes the ALTLS value (altitude at line-of-sight) for every
           pixel of an XVIS image.
        ===>    [ These are actually radial distances, not altitudes.]
     CATEGORY:

     CALLING SEQUENCE:
           XV_GET_ALTLS
     INPUTS:
           NONE
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           NONE
     COMMON BLOCKS:
           XV_RECORD_DATA
           XV_FILE_DATA
           XV_DERIVED_DATA
           XV_FLAGS
     NOTES:
           This routine is useful only within the XVIS application
           It uses COMMON blocks extensively and certain values within
           the blocks must be set prior to invocation.
     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## XV_GET_PHIS

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           XV_GET_PHIS
     PURPOSE:
           Computes the PHI angles at every pixel within an XVIS image.
      ===>  [ PHI is the angle between look direction vector and the
                 negative s/c position vector ]
     CATEGORY:

     CALLING SEQUENCE:
           XV_GET_PHIS
     INPUTS:
           NONE
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           NONE
     COMMON BLOCKS:
           XV_RECORD_DATA
           XV_FILE_DATA
           XV_DERIVED_DATA
           XV_FLAGS
     NOTES:
           This routine is useful only within the XVIS application
           It uses COMMON blocks extensively and certain values within
           the blocks must be set prior to invocation.
     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## XV_LOOKV_TO_GCI[1]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           XV_LOOKV_TO_GCI
     PURPOSE:
           Converts the XVIS LOOK vector to GCI coordinates
     CATEGORY:

     CALLING SEQUENCE:
           XV_LOOKV_TO_GCI
     INPUTS:
           NONE
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           NONE
     COMMON BLOCKS:
           XV_RECORD_DATA
           XV_FILE_DATA
           XV_DERIVED_DATA
           XV_FLAGS
     NOTES:
           This routine is useful only within the XVIS application
           It uses COMMON blocks extensively and certain values within
           the blocks must be set prior to invocation.
     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97
    	Rae Dvorsky, 03/19/05

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## XV_LOOKV_TO_GCI[2]

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           XV_LOOKV_TO_GCI
     PURPOSE:
           Converts the XVIS LOOK vector to GCI coordinates
     CATEGORY:

     CALLING SEQUENCE:
           XV_LOOKV_TO_GCI
     INPUTS:
           NONE
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           NONE
     COMMON BLOCKS:
           XV_RECORD_DATA
           XV_FILE_DATA
           XV_DERIVED_DATA
           XV_FLAGS
     NOTES:
           This routine is useful only within the XVIS application
           It uses COMMON blocks extensively and certain values within
           the blocks must be set prior to invocation.
     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/vis.pro)

## XV_SCALE_COLOR_TABLE

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           XV_SCALE_COLOR_TABLE
     PURPOSE:
           Fits the color table from the CDF file into the table
           size used in the current IDL session and the min/max
           values specified.
     CATEGORY:

     CALLING SEQUENCE:
           XV_SCALE_COLOR_TABLE
     INPUTS:
           MIN = actual colors begin here.  Anything under this value
                 is set to the min value.
           MAX = actual colors end here.  Anything over this value
                 is set to the max value.
     KEYWORD PARAMETERS:

     OUTPUTS:

     COMMON BLOCKS:
           COLORS
     NOTES:

     MODIFICATION HISTORY:

(See external/CDAWlib/viscal.pro)

## XV_UNDISTORT

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
      XV_UNDISTORT

     PURPOSE:
      'Warps' a 256 by 256 pixel VIS image to display
      the image in the correct spatial resolution

     CATEGORY:
      VIS image analysis

     INPUTS:
      A VIS image

     KEYWORD PARAMETERS:
      None

     OUTPUTS:
      An 'undistorted' image

     COMMON BLOCKS:
      XV_FILE_DATA

     SIDE EFFECTS:
      None

     RESTRICTIONS:
      None

     EXAMPLE:
      NewImage = XV_UNDISTORT(Image)

     MODIFICATION HISTORY:
      Written by Kenny Hunt, 9/97

(See external/CDAWlib/viscal.pro)

## XV_UNPACK_WHERE

[Previous Routine] [Next Routine] [List of Routines]

     NAME:
           XV_UNPACK_WHERE
     PURPOSE:
           An often used utility that converts a single value
           index into a vis image into it's respective row,col
           values.
     CATEGORY:

     CALLING SEQUENCE:

     INPUTS:
           INDEX == array of indices into a vis image.
     KEYWORD PARAMETERS:
           NONE
     OUTPUTS:
           ROW == array of row indices
           COL == array of column indices
     COMMON BLOCKS:
           None
     NOTES:

     MODIFICATION HISTORY:
           Kenny Hunt, 9/1/97

     Copyright (C) 1998, The University of Iowa Department of Physics and Astronomy
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.

(See external/CDAWlib/viscal.pro)

## XYZMAP

[Previous Routine] [Next Routine] [List of Routines]

     NAME: XYZMAP.PRO

     PURPOSE:  Display of stations and satellite traces on a world projection

     CALLING SEQUENCE:

       xyzmap,lat,lon,alt,station,trace=trace,vlat=vlat,iproj=iproj,limit=limit,$
              latdel=latdel,londel=londel,Ttitle=thetitle,$
              pmode=pmode,rng_val=rng_val,num_int=num_int,$
              ptype=ptype,lthik=lthik,symsiz=symsiz,symcol=symcol,$
              charsize=charsize,xmargin=xmargin,ymargin=ymargin,$
              xoffset=xoffset,yoffset=yoffset,lnlabel=lnlabel,_extra=extras

     VARIABLES:

     Input:

     lat(*)     - an N element array of geographic latitudes
     lon(*)     - an N element array of geographic longitudes
     alt(*)     _ an N element array of geographic altitudes
     station(*) - an N element array of station names

     Keyword Parameters:

     trace=trace		- if set, then plot lat,lon connected lines.
    			  if not set, just plot the map, no addition lines.
     vlat=vlat		- array of map_set argument;
    			    (0) latitude center of map
      			    (1) longitude center of map
    			    (2) rotation of map
     iproj=iproj		- map_set projection
     limit=limit		- map_set limits
     latdel=latdel		- latitude interval
     londel=londel		- longitude interval
     Ttitle=thetitle	- Title for plot
     pmode=pmode		- image number or window frame
     rng_val=rng_val       - time range
     num_int=num_int       - number of intervals over time range
     ptype=ptype		- plot type:  0 - trace; 1 - station
     lthik=lthik           - line thickness
     symsiz=symsiz         - station symbol size
     symcol=symcol         - station symbol color
     charsize=charsize     - character size
     xmargin=xmargin       - left - right margins
     ymargin=ymargin 	- top - bottom margins
     xoffset=xoffset	- caption offset from left
     yoffset=yoffset	- caption offset from bottom
     lnlabel=lnlabel	- line labels
     nocont=nocont         - no continent outline

     REQUIRED PROCEDURES:

       none

     History

             1.0  R. Baldwin  HSTX     12/20/95
    		Initial version
    	  1.1  T. Kovalick HSTX
    		Modified to read allow station locations (the lat,
    		lon and station varaibles to be read in from a
    		ascii file in addition to coming from a cdf.
    		Changed some of the labeling slightly to accommodate
    		this.

             1.2  R. Baldwin HSTX
                   Added orbit labeling code

    Copyright 1996-2013 United States Government as represented by the
    Administrator of the National Aeronautics and Space Administration.
    All Rights Reserved.

(See external/CDAWlib/xyzmap.pro)

## YMD2DN

[Previous Routine] [List of Routines]

     NAME:
           YMD2DN
     PURPOSE:
           Convert from year, month, day to day number of year.
     CATEGORY:
     CALLING SEQUENCE:
           dy = ymd2dn(yr,m,d)
     INPUTS:
           yr = year (like 1988).               in
           m = month number (like 11 = Nov).    in
           d = day of month (like 5).           in
     KEYWORD PARAMETERS:
     OUTPUTS:
           dy = day number in year (like 310).  out
     COMMON BLOCKS:
     NOTES:
     MODIFICATION HISTORY:
           Written by R. Sterner, 20 June, 1985.
           Johns Hopkins University Applied Physics Laboratory.
           RES 18 Sep, 1989 --- converted to SUN
           R. Sterner, 1997 Feb 3 --- Made work for arrays.

     Copyright (C) 1985, Johns Hopkins University/Applied Physics Laboratory
     This software may be used, copied, or redistributed as long as it is not
     sold and this copyright notice is reproduced on each copy made.  This
     routine is provided as is without any express or implied warranties
     whatsoever.  Other limitations apply as described in the file disclaimer.txt.

(See external/CDAWlib/ymd2dn.pro)