001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2015
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
031
032import java.awt.Image;
033import java.awt.Toolkit;
034import java.awt.geom.Rectangle2D;
035import java.awt.image.BufferedImage;
036import java.io.BufferedReader;
037import java.io.InputStream;
038import java.io.InputStreamReader;
039import java.rmi.RemoteException;
040import java.util.ArrayList;
041import java.util.HashMap;
042import java.util.Hashtable;
043import java.util.List;
044
045import edu.wisc.ssec.mcidasv.control.LambertAEA;
046
047import ucar.unidata.data.BadDataException;
048import ucar.unidata.data.CompositeDataChoice;
049import ucar.unidata.data.DataCategory;
050import ucar.unidata.data.DataChoice;
051import ucar.unidata.data.DataSelection;
052import ucar.unidata.data.DataSourceDescriptor;
053import ucar.unidata.data.DirectDataChoice;
054import ucar.unidata.data.grid.GridUtil;
055import ucar.unidata.data.imagery.ImageInfo;
056import ucar.unidata.util.IOUtil;
057import ucar.unidata.util.Misc;
058import visad.Data;
059import visad.FlatField;
060import visad.FunctionType;
061import visad.Gridded2DSet;
062import visad.Gridded3DSet;
063import visad.Linear2DSet;
064import visad.RealTupleType;
065import visad.RealType;
066import visad.SampledSet;
067import visad.Unit;
068import visad.VisADException;
069import visad.georef.MapProjection;
070import visad.util.ImageHelper;
071
072
073/**
074 * This is an implementation that will read in a generic data file
075 * and return a single Data choice that is a VisAD Data object.
076 */
077public class FlatFileDataSource extends ucar.unidata.data.FilesDataSource {
078
079    /**
080     *  Parameterless ctor
081     */
082    public FlatFileDataSource() {}
083
084
085    /**
086     * Just pass through to the base class the ctor arguments.
087     * @param descriptor    Describes this data source, has a label etc.
088     * @param filename      This is the filename (or url) that
089     *                      points to the actual data source.
090     * @param properties General properties used in the base class
091     *
092     * idv    * @throws VisADException   problem getting the data
093     */
094    public FlatFileDataSource(DataSourceDescriptor descriptor,
095                              String filename, Hashtable properties)
096            throws VisADException {
097        super(descriptor, filename, "Image flat file data source", properties);
098        System.out.println("FlatFileDataSource.descriptor: " + descriptor.toString());
099        System.out.println("FlatFileDataSource.filename: " + filename);
100        System.out.println("FlatFileDataSource.properties: " + properties.toString());
101    }
102
103    /**
104     * This method is called at initialization time and  should create
105     * a set of {@link ucar.unidata.data.DirectDataChoice}-s  and add them
106     * into the base class managed list of DataChoice-s with the method
107     * addDataChoice.
108     */
109    protected void doMakeDataChoices() {
110        String xmlFile = getFilePath();
111        List bandsDefault = new ArrayList();
112        bandsDefault.add("Band 1");
113            String name = getProperty("FLAT.NAME", "Unknown name");
114            List bandNames = (List)getProperty("FLAT.BANDNAMES", bandsDefault);
115            List bandFiles = (List)getProperty("FLAT.BANDFILES", bandsDefault);
116            
117            int lines = getProperty("FLAT.LINES", (int)0);
118            int elements = getProperty("FLAT.ELEMENTS", (int)0);
119            String unit = getProperty("FLAT.UNIT", "");
120            int stride = getProperty("FLAT.STRIDE", (int)1);
121
122            if (bandNames.size() == bandFiles.size()) {
123                    for (int i=0; i<bandNames.size(); i++) {
124                        System.out.println(bandNames.get(i) + ": " + bandFiles.get(i));
125                    }
126            }
127            else {
128                System.err.println("bandNames: " + bandNames.toString());
129                System.err.println("bandFiles: " + bandFiles.toString());
130                System.err.println("Huh... bandNames (" + bandNames.size() + ") and bandFiles (" + bandFiles.size() + ") should be the same size");
131            }
132            
133        Hashtable imageProps = Misc.newHashtable(DataChoice.PROP_ICON, "/auxdata/ui/icons/Earth16.gif");
134
135            // Navigation
136            String navType = getProperty("NAV.TYPE", "UNKNOWN");
137            double ulLat = 0;
138            double ulLon = 0;
139            double lrLat = 0;
140            double lrLon = 0;
141            String latFile = null;
142            String lonFile = null;
143            if (navType == "FILES") {
144                latFile = getProperty("FILE.LAT", "");
145                lonFile = getProperty("FILE.LON", "");
146            }
147            else if (navType == "BOUNDS") {
148                    ulLat = getProperty("BOUNDS.ULLAT", (double)0);
149                    ulLon = getProperty("BOUNDS.ULLON", (double)0);
150                    lrLat = getProperty("BOUNDS.LRLAT", (double)0);
151                    lrLon = getProperty("BOUNDS.LRLON", (double)0);
152            }
153            else {
154                System.err.println("FlatFileDataSource: Unknown navType: " + navType);
155            }
156            int scale = getProperty("NAV.SCALE", (int)1);
157            boolean eastPositive = getProperty("NAV.EASTPOS", false);
158            
159            // Format
160            String formatType = getProperty("FORMAT.TYPE", "UNKNOWN");
161            if (formatType == "BINARY") {
162                int format = getProperty("BINARY.FORMAT", HeaderInfo.kFormat1ByteUInt);
163                String interleave = getProperty("BINARY.INTERLEAVE", HeaderInfo.kInterleaveSequential);
164                boolean bigEndian = getProperty("BINARY.BIGENDIAN", false);
165                int offset = getProperty("BINARY.OFFSET", 0);
166                
167                    List categories = DataCategory.parseCategories("IMAGE", false);
168            CompositeDataChoice cdc = new CompositeDataChoice(this, "", name, name, null);
169            for (int i=0; i<bandFiles.size(); i++) {
170                FlatFileReader dataChoiceData = new FlatFileReader((String)bandFiles.get(i), lines, elements);
171                        dataChoiceData.setBinaryInfo(format, interleave, bigEndian, offset, i+1, bandFiles.size());
172                        dataChoiceData.setUnit(unit);
173                        dataChoiceData.setEastPositive(eastPositive);
174                        dataChoiceData.setStride(stride);
175                if (latFile != null && lonFile != null) {
176                        dataChoiceData.setNavFiles(latFile, lonFile, scale);
177                }
178                else {
179                        dataChoiceData.setNavBounds(ulLat, ulLon, lrLat, lrLon);
180                }
181                String bandName = (String)bandNames.get(i);
182                    DirectDataChoice ddc = new DirectDataChoice(this, dataChoiceData, bandName, bandName, categories, imageProps);
183                    cdc.addDataChoice(ddc);
184            }
185                        addDataChoice(cdc);
186            System.err.println("Still working on binary data...");
187            }
188            else if (formatType == "ASCII") {
189                String delimiter = getProperty("ASCII.DELIMITER", "");
190                
191                    List categories = DataCategory.parseCategories("IMAGE", false);
192            CompositeDataChoice cdc = new CompositeDataChoice(this, "", name, name, null);
193            for (int i=0; i<bandFiles.size(); i++) {
194                FlatFileReader dataChoiceData = new FlatFileReader((String)bandFiles.get(i), lines, elements);
195                        dataChoiceData.setAsciiInfo(delimiter, 1);
196                        dataChoiceData.setUnit(unit);
197                        dataChoiceData.setEastPositive(eastPositive);
198                        dataChoiceData.setStride(stride);
199                if (latFile != null && lonFile != null) {
200                        dataChoiceData.setNavFiles(latFile, lonFile, scale);
201                }
202                else {
203                        dataChoiceData.setNavBounds(ulLat, ulLon, lrLat, lrLon);
204                }
205                String bandName = (String)bandNames.get(i);
206                    DirectDataChoice ddc = new DirectDataChoice(this, dataChoiceData, bandName, bandName, categories, imageProps);
207                    cdc.addDataChoice(ddc);
208            }
209                        addDataChoice(cdc);
210            System.err.println("Still working on ascii data...");
211            }
212            else if (formatType == "IMAGE") {
213                    List categories = DataCategory.parseCategories("RGBIMAGE", false);
214                    FlatFileReader dataChoiceData = new FlatFileReader((String)bandFiles.get(0), lines, elements);
215                dataChoiceData.setImageInfo();
216                dataChoiceData.setUnit(unit);
217                dataChoiceData.setEastPositive(eastPositive);
218                dataChoiceData.setStride(stride);
219                if (latFile != null && lonFile != null) {
220                        dataChoiceData.setNavFiles(latFile, lonFile, scale);
221                }
222                else {
223                        dataChoiceData.setNavBounds(ulLat, ulLon, lrLat, lrLon);
224                }
225                String bandName = (String)bandNames.get(0);
226                DirectDataChoice ddc = new DirectDataChoice(this, dataChoiceData, bandName, bandName, categories, imageProps);
227                addDataChoice(ddc);
228            }
229            else {
230                System.err.println("FlatFileDataSource: Unknown formatType: " + formatType);
231            }
232    }
233    
234    /**
235     * This method should create and return the visad.Data that is
236     * identified by the given {@link ucar.unidata.data.DataChoice}.
237     *
238     * @param dataChoice     This is one of the DataChoice-s that was created
239     *                       in the doMakeDataChoices call above.
240     * @param category       The specific {@link ucar.unidata.data.DataCategory}
241     *                       which the {@link ucar.unidata.idv.DisplayControl}
242     *                       was instantiated with. Usually can be ignored.
243     * @param dataSelection  This may contain a list of times which
244     *                       subsets the request.
245     * @param requestProperties  extra request properties
246     * @return The {@link visad.Data} object represented by the given dataChoice
247     *
248     * @throws RemoteException    Java RMI problem
249     * @throws VisADException     VisAD problem
250     */
251    protected Data getDataInner(DataChoice dataChoice, DataCategory category,
252                DataSelection dataSelection,
253                Hashtable requestProperties)
254    throws VisADException, RemoteException {
255        FlatFileReader stuff = (FlatFileReader) dataChoice.getId();
256        return stuff.getData();
257    }
258
259}
260