Error when calling ENVI_WRITE_ENVI_FILE [message #86313] |
Fri, 25 October 2013 08:35  |
Simon Mitchell
Messages: 6 Registered: October 2013
|
Junior Member |
|
|
Hi All,
I am getting an error when using the ENVI_WRITE_ENVI_FILE command. Note that I am a beginner with using IDL.
The error that I am getting is:
ERROR: "FLOAT: Struct expression not allowed in this context: DATA." The result may be invalid.
I have to add, that this error does not stop my code from creating a file, but the values are not what I am expecting.
A little background on what I am trying to do.
I want to be able to replicate in IDL (for batch script) opening multiple ASCII files (each representing a band of image data) and then saving them as an ENVI Standard file with multiple bands.
So essentially doing the "File->Open External File->Generic Formats->ASCII" for three files, then "Save File As->ENVI Standard" as one file with three bands in BSQ format.
My code is as follows, and I am just using a dummy test image of 11 samples and lines as my input, with 6 header lines.
PRO COMBINE_ASCII
opendir = 'D:\Directory'
redfile = opendir+'red_output_short.txt'
mirfile = opendir+'mir_template_short.txt'
tirfile = opendir+'tir_template_short.txt'
ofname = opendir+'random_image_1'
descrip = 'Random point image #1'
ns = 11
nl = 11
nc = 3*nl
rnd_data = FLTARR([ns], [nc]) ;float array of ns = 11, nl = 11 for 3 bands
;rnd_data = FLTARR([ns],[nl],3)
;Open the files
OPENR, lun_red, redfile, /GET_LUN
red_data = READ_ASCII(redfile, DATA_START = 6, DELIMITER = string(9B))
rnd_data = [red_data]
OPENR, lun_mir, mirfile, /GET_LUN
mir_data = READ_ASCII(mirfile, DATA_START = 6, DELIMITER = string(9B))
rnd_data = [[rnd_data], [mir_data]]
OPENR, lun_tir, tirfile, /GET_LUN
tir_data = READ_ASCII(tirfile, DATA_START = 6, DELIMITER = string(9B))
rnd_data = [[rnd_data], [tir_data]]
;rnd_data = [[red_data],[mir_data],[tir_data]]
;OPENW, lun_out, ofname, /GET_LUN
print, rnd_data
;reddata = READ_ASCII(redfile, DATA_START = 6)
;mirdata = READ_ASCII(mirfile, DATA_START = 6)
;tirdata = READ_ASCII(tirfile, DATA_START = 6)
ENVI_WRITE_ENVI_FILE, rnd_data, FILE_TYPE = 4, INTERLEAVE = 0, NB = 3, NS = ns, NL = nl, OUT_DT = 4, OUT_NAME = ofname
; FILE_TYPE = 4
ENVI_SETUP_HEAD, FNAME = ofname, NS = ns, NL = nl, NB = 3, $
XSTART = 0, YSTART = 0, DATA_TYPE = 1, INTERLEAVE = 0, $
file_type = 4, $
DESCRIP = descrip, /WRITE, /OPEN
CLOSE, /ALL
END
I am wondering if any one can tell me where I am going wrong, or could suggest a better way of doing this!!! As you can probably guess, I am not the best idl coder and have only been using it for a short time, but I think I may be doing something wrong with the array concatenation.
Many thanks in advance for your help.
Simon
|
|
|
Re: Error when calling ENVI_WRITE_ENVI_FILE [message #86315 is a reply to message #86313] |
Fri, 25 October 2013 09:02   |
Phillip Bitzer
Messages: 223 Registered: June 2006
|
Senior Member |
|
|
Hi Simon-
Well, you're not getting what you think in the "data" variables. Check out this from the help for READ_ASCII:
The result is an IDL structure array containing the data
And this variable (ultimately) is what you're using in ENVI_WRITE_ENVI_FILE. Only problem is, according to the help, the parameter that you should pass is:
This is a 2D or 3D data array of type byte, integer, unsigned integer, long integer, unsigned long integer, long 64-bit integer, unsigned long 64-bit integer, floating-point, double-precision, complex, or double-precision complex.
You have to extract the pertinent data from the READ_ASCII function, and put it in the format ENVI_WRITE_ENVI_FILE expects. (I'll note there's probably better ways than using READ_ASCII here, but you can certainly get it to work.)
There's a couple of other things going on. Consider these lines:
rnd_data = FLTARR([ns], [nc]) ;float array of ns = 11, nl = 11 for 3 bands
...
red_data = READ_ASCII(redfile, DATA_START = 6, DELIMITER = string(9B))
rnd_data = [red_data]
Basically, the first line isn't doing anything for you, because you change the variable (more formally, dynamically cast the variable) from an array to a structure in the last line.
Hope this helps!
|
|
|
|
Re: Error when calling ENVI_WRITE_ENVI_FILE [message #86335 is a reply to message #86321] |
Mon, 28 October 2013 08:55   |
Simon Mitchell
Messages: 6 Registered: October 2013
|
Junior Member |
|
|
Thanks for responding Phil and Josh.
I guess I'm just not understanding what is going on here.
What is the difference between a structure array and a data array?
When I use the code
red_data = READ_ASCII(redfile, DATA_START = 6, DELIMITER = string(9B))
rnd_data = [red_data]
print, red_data
print, rnd_data
I get the result (using a 3x3 image as an example)
{
1 1 1
1 1 1
1 1 1
}
{
1 1 1
1 1 1
1 1 1
}
I then want to add the second band to the data (to make it BSQ format)
mir_data = READ_ASCII(mirfile, DATA_START = 6, DELIMITER = string(9B))
rnd_data = [[rnd_data], [mir_data]]
print, rnd_data
I get
{
1 1 1
1 1 1
1 1 1
}{
2 2 2
2 2 2
2 2 2
}
when what I would expect would be
{
1 1 1
1 1 1
1 1 1
2 2 2
2 2 2
2 2 2
}
and so on for the third band. Am I correct in my assumption? I assume that what I'm actually getting is a [3,3,3] array, rather than my expected [3,9] array.
But I'm also not understanding is why the ENVI_WRITE_ENVI_FILE is not accepting this data?
Would you please be able to step me through my questions?
Or if someone has a better method for loading ASCII files into an ENVI standard image, could they please pass this on to me.
Many thanks in advance
Simon
|
|
|
Re: Error when calling ENVI_WRITE_ENVI_FILE [message #86337 is a reply to message #86335] |
Mon, 28 October 2013 09:34   |
Phillip Bitzer
Messages: 223 Registered: June 2006
|
Senior Member |
|
|
Hi Simon-
First, some terminology. You can have an "array of structures". You can also have a "structure with tags that are arrays".
Before we jump into it, the use of help is much more, well, helpful, than print. You'll see this in action below.
Consider this variable:
IDL> str = {data:FLTARR(3, 3)}
Notice "str" is a structure, and "data" is a tag (or field) of "str". Try this:
IDL> help, str
So, "str" is in fact a structure. In order to access the tag data, we use:
IDL> help, str.data
So, str.data (again, the tag "data" in the structure "str") is a 3x3 float array.
Print it if you'd like:
IDL> print, str.data
This is how you deal with a "structure that has tags that are arrays".
-------
We can take this further. Consider:
arrOfStr = REPLICATE(str, 2)
Now, 'arrofStr' is an "array of structures". See for yourself:
IDL> help, arrOfStr
You can print this too:
IDL> print, arrOfStr
What you *really* want is the data tag from each structure:
IDL> help, arrOfStr.data
IDL> print, arrOfStr.data
-------
|
|
|
Re: Error when calling ENVI_WRITE_ENVI_FILE [message #86343 is a reply to message #86337] |
Mon, 28 October 2013 18:07   |
Josh Sixsmith
Messages: 13 Registered: December 2012
|
Junior Member |
|
|
> What you *really* want is the data tag from each structure:
>
> IDL> help, arrOfStr.data
>
> IDL> print, arrOfStr.data
>
>
>
> -------
Exactly what Phillip has mentioned. Use the tag names to get at the actual data array contained within the structure. The "data" argument to "ENVI_WRITE_ENVI_FILE" is the array itself, not a structure that contains the arrays.
You could pre-allocate an array that will contain all the bands.
eg
red_data = READ_ASCII(redfile, DATA_START = 6, DELIMITER = string(9B))
columns = 4000 ; or whatever it may be
rows = 4000
bands = 7
all_bands = FLTARR(columns, rows, bands)
all_bands[*,*,0] = red_data.data_tag_name ;data_tag_name could be data as in the example provided by Phillip.
and so on for all the necessary bands.
bnames=['1','2','3','4','5','6','7']
Then
ENVI_WRITE_ENVI_FILE, all_bands, bnames=bnames, nb=bands, nl=rows, ns=columns, out_name='my_envi_file'
Hope that helps.
Cheers
Josh
|
|
|
|