001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2023
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see http://www.gnu.org/licenses.
027 */
028
029package edu.wisc.ssec.mcidasv.data;
030
031import java.io.BufferedReader;
032import java.io.File;
033import java.io.FileReader;
034
035import java.util.ArrayList;
036import java.util.List;
037
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040
041/**
042 * Representation of an AXFORM header file.
043 */
044public class AxformInfo extends HeaderInfo {
045
046    private static final Logger logger = 
047        LoggerFactory.getLogger(AxformInfo.class);
048    
049    /** The url */
050    private String dataFile = "";
051    private boolean isAxform = false;
052
053    /**
054     * Ctor for xml encoding
055     */
056    public AxformInfo() {}
057
058    /**
059     * CTOR
060     *
061     * @param thisFile File to use. Cannot be {@code null}.
062     */
063    public AxformInfo(File thisFile) {
064        this(thisFile.getAbsolutePath());
065    }
066
067    /**
068     * CTOR
069     *
070     * @param filename The filename
071     */
072    public AxformInfo(String filename) {
073        super(filename);
074    }
075
076    /**
077     * Is the file an AXFORM header file?
078     * 
079     * @return Whether or not the file is a valid AXFORM header file.
080     */
081    public boolean isAxformInfoHeader() {
082        parseHeader();
083        return isAxform;
084    }
085
086    /**
087     * Which band number is latitude?
088     * 
089     * @return Always returns {@code 1} for this class.
090     */
091    public int getLatBandNum() {
092        return 1;
093    }
094
095    /**
096     * Get the latitude grid file.
097     *
098     * @return Either the latitude grid file or an empty {@code String}.
099     */
100    public String getLatBandFile() {
101        parseHeader();
102        List bandFiles = getParameter(NAVFILES, new ArrayList());
103        if (bandFiles.size() != 2) {
104            return "";
105        }
106        return (String)(bandFiles.get(0));
107    }
108
109    /**
110     * Which band number is longitude?
111     * 
112     * @return Always returns {@code 1} for this class.
113     */
114    public int getLonBandNum() {
115        return 1;
116    }
117
118    /**
119     * Get the longitude grid file.
120     * 
121     * @return Either the longitude grid file or an empty {@code String}.
122     */
123    public String getLonBandFile() {
124        parseHeader();
125        List bandFiles = getParameter(NAVFILES, new ArrayList());
126        if (bandFiles.size() != 2) {
127            return "";
128        }
129        return (String)(bandFiles.get(1));
130    }
131
132    /**
133     * Parse a potential AXFORM header file.
134     */
135    protected void parseHeader() {
136        if (haveParsed()) return;
137        if (!doesExist()) {
138            isAxform = false;
139            return;
140        }
141
142        try {
143            BufferedReader br = new BufferedReader(new FileReader(getFilename()));
144            int lineNum = 0;
145            String line;
146            String description = "";
147            boolean gotFiles = false;
148
149            List bandNames = new ArrayList();
150            List bandFiles = new ArrayList();
151
152            String latFile = "";
153            String lonFile = "";
154            File thisFile = new File(getFilename());
155            String parent = thisFile.getParent();
156            if (parent == null) parent=".";
157
158            while ((line = br.readLine()) != null) {
159                lineNum++;
160                if (line.trim().equals("Space Science & Engineering Center")) {
161                    isAxform = true;
162                    continue;
163                }
164                
165                if (!isAxform) {
166                    break;
167                }
168
169                if (line.length() < 80) {
170                    if (lineNum > 15) {
171                        gotFiles = true;
172                    }
173                    continue;
174                }
175
176                // Process the description from lines 5 and 6
177                if (lineNum == 5) {
178                    description += line.substring(13, 41).trim();
179                } else if (lineNum == 6) {
180                    description += " " + line.substring(14, 23).trim() + " " + line.substring(59, 71).trim();
181                    setParameter(DESCRIPTION, description);
182                }
183
184                // Process the file list starting at line 15
185                else if (lineNum >= 15 && !gotFiles) {
186                    String parameter = line.substring(0, 13).trim();
187                    if (parameter.equals("Header")) {
188                        isAxform = true;
189                    } else if (parameter.equals("Latitude")) {
190                        latFile = parent + "/" + line.substring(66).trim();
191                    } else if (parameter.equals("Longitude")) {
192                        lonFile = parent + "/" + line.substring(66).trim();
193                    } else {
194                        setParameter(LINES, Integer.parseInt(line.substring(24, 31).trim()));
195                        setParameter(ELEMENTS, Integer.parseInt(line.substring(32, 40).trim()));
196                        setParameter(UNIT, parameter);
197                        String band = line.substring(19, 23).trim();
198                        String format = line.substring(41, 59).trim();
199                        logger.trace("looking at format line: {}", format);
200                        if (format.indexOf("ASCII") >= 0) {
201                            setParameter(DATATYPE, kFormatASCII);
202                        } else if (format.indexOf("8 bit") >= 0) {
203                            setParameter(DATATYPE, kFormat1ByteUInt);
204                        } else if (format.indexOf("16 bit") >= 0) {
205                            setParameter(DATATYPE, kFormat2ByteSInt);
206                        } else if (format.indexOf("32 bit") >= 0) {
207                            setParameter(DATATYPE, kFormat4ByteSInt);
208                        }
209                        String filename = line.substring(66).trim();
210                        filename = parent + "/" + filename;
211                        bandFiles.add(filename);
212                        bandNames.add("Band " + band);
213                    }
214                }
215
216                // Look for the missing value, bail when you find it
217                else if (gotFiles) {
218                    if (line.indexOf("Navigation files missing data value") >= 0) {
219                        setParameter(MISSINGVALUE, Float.parseFloat(line.substring(44, 80).trim()));
220                        break;
221                    }
222                }
223
224                setParameter(BANDNAMES, bandNames);
225                setParameter(BANDFILES, bandFiles);
226
227                List latlonFiles = new ArrayList();
228                latlonFiles.add(latFile);
229                latlonFiles.add(lonFile);
230                setParameter(NAVFILES, latlonFiles);
231
232            }
233            br.close();
234        } catch (Exception e) {
235            logger.error("Could not parse header!", e);
236        }
237    }
238}