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