1515import com .bc .fiduceo .util .NetCDFUtils ;
1616import com .bc .fiduceo .util .TimeUtils ;
1717import com .bc .fiduceo .util .VariableProxy ;
18+ import org .esa .snap .dataio .netcdf .PartialDataCopier ;
1819import ucar .ma2 .*;
20+ import ucar .nc2 .AttributeContainer ;
1921import ucar .nc2 .Variable ;
2022
23+ import java .awt .geom .Rectangle2D ;
2124import java .io .File ;
2225import java .io .IOException ;
2326import java .util .ArrayList ;
@@ -36,6 +39,10 @@ class WindsatReader extends NetCDFReader {
3639 private PixelLocator pixelLocator ;
3740 private TimeLocator timeLocator ;
3841
42+ private Dimension productSize ;
43+ private int productWidth ;
44+ private int productHeight ;
45+
3946 WindsatReader (ReaderContext readerContext ) {
4047 this .geometryFactory = readerContext .getGeometryFactory ();
4148 variables2D = new ArrayList <>();
@@ -74,6 +81,7 @@ static int getIndex(String value, String[] strings) {
7481 @ Override
7582 public void open (File file ) throws IOException {
7683 super .open (file );
84+ initProductSize ();
7785 }
7886
7987 @ Override
@@ -134,15 +142,15 @@ public PixelLocator getSubScenePixelLocator(Polygon sceneGeometry) throws IOExce
134142 @ Override
135143 public TimeLocator getTimeLocator () throws IOException {
136144 if (timeLocator == null ) {
137- final Array timeArray = arrayCache . get ("time" );
138- final Number fillValue = getFillValue ("time" , timeArray );
145+ final Variable variable = netcdfFile . findVariable ("time" );
146+ final Number fillValue = NetCDFUtils . getFillValue (variable );
139147 final int [] origin = {0 , 0 , 0 , 2 }; // select layer for "fore" and 18 GHz tb 2022-11-28
140- final int [] shape = timeArray .getShape ();
148+ final int [] shape = variable .getShape ();
141149 shape [2 ] = 1 ; // one view layer tb 2022-11-28
142150 shape [3 ] = 1 ; // one frequency layer tb 2022-11-28
143151
144152 try {
145- final Array timeArraySection = timeArray . section (origin , shape ).reduce ();
153+ final Array timeArraySection = variable . read (origin , shape ).reduce ();
146154 timeLocator = new TimeLocator_SecondsSince2000 (timeArraySection , fillValue .doubleValue ());
147155 } catch (InvalidRangeException e ) {
148156 throw new IOException (e .getMessage ());
@@ -192,48 +200,82 @@ public Array readRaw(int centerX, int centerY, Interval interval, String variabl
192200 }
193201
194202 return resultArray ;
195- } else if (variables2D .contains (variableName )) {
196- final Array array = arrayCache .get (variableName );
197- final Number fillValue = getFillValue (variableName , array );
198- return RawDataReader .read (centerX , centerY , interval , fillValue , array , getProductSize ());
199- } else {
200- // extract layer indices and NetCDF file variable name from variable name
201- final ArrayInfo arrayInfo = extractArrayInfo (variableName );
202-
203- final Array array = arrayCache .get (arrayInfo .ncVarName );
204- final Number fillValue = getFillValue (arrayInfo .ncVarName , array );
205-
206- final int [] origin ;
207- final int [] shape ;
208- if (arrayInfo .freqIdx >= 0 ) {
209- origin = new int [4 ];
210- origin [2 ] = arrayInfo .lookIdx ;
211- origin [3 ] = arrayInfo .freqIdx ;
212-
213- shape = array .getShape ();
214- shape [2 ] = 1 ;
215- shape [3 ] = 1 ;
203+ }
204+ final int winWith = interval .getX ();
205+ final int winHeight = interval .getY ();
206+ final int offsetX = centerX - winWith / 2 ;
207+ final int offsetY = centerY - winHeight / 2 ;
208+ final boolean isWindowInside = RawDataReader .isWindowInside (offsetX , offsetY , winWith , winHeight , productWidth , productHeight );
209+
210+ if (variables2D .contains (variableName )) {
211+ final Variable variable = netcdfFile .findVariable (variableName );
212+ if (isWindowInside ) {
213+ return variable .read (new int []{offsetY , offsetX }, new int []{winHeight , winWith });
216214 } else {
217- origin = new int [4 ];
218- origin [0 ] = arrayInfo .polIdx ;
219- origin [1 ] = arrayInfo .lookIdx ;
220-
221- shape = array .getShape ();
222- shape [0 ] = 1 ;
223- shape [1 ] = 1 ;
215+ final Rectangle2D insideWindow = RawDataReader .getInsideWindow (offsetX , offsetY , winWith , winHeight , productWidth , productHeight );
216+ final int [] origin = {(int ) insideWindow .getY (), (int ) insideWindow .getX ()};
217+ final int [] shape = {(int ) insideWindow .getHeight (), (int ) insideWindow .getWidth ()};
218+ final Array insideRead = variable .read (origin , shape );
219+ final Number fillValue = NetCDFUtils .getFillValue (variable );
220+ final Array array = NetCDFUtils .create (insideRead .getDataType (), new int []{winHeight , winWith }, fillValue );
221+ final int targetOffsY = Math .min (offsetY , 0 );
222+ final int targetOffsX = Math .min (offsetX , 0 );
223+ PartialDataCopier .copy (new int []{targetOffsY , targetOffsX }, insideRead , array );
224+ return array ;
224225 }
225-
226- final Array section = array .section (origin , shape ).copy ();
227- return RawDataReader .read (centerX , centerY , interval , fillValue , section , getProductSize ());
228226 }
229- }
230227
231- private Number getFillValue (String variableName , Array array ) throws IOException {
232- Number fillValue = arrayCache .getNumberAttributeValue (NetCDFUtils .CF_FILL_VALUE_NAME , variableName );
233- if (fillValue == null ) {
234- fillValue = NetCDFUtils .getDefaultFillValue (array );
228+ // extract layer indices and NetCDF file variable name from variable name
229+ final ArrayInfo arrayInfo = extractArrayInfo (variableName );
230+ final Variable variable = netcdfFile .findVariable (arrayInfo .ncVarName );
231+ final int [] shape = variable .getShape ();
232+ final int [] origin = new int [4 ];
233+ final int xDimPos ;
234+ final int yDimPos ;
235+ final int lookPos ;
236+ final int freqPolPos ;
237+ if (arrayInfo .freqIdx >= 0 ) {
238+ yDimPos = 0 ;
239+ xDimPos = 1 ;
240+ lookPos = 2 ;
241+ freqPolPos = 3 ;
242+ } else {
243+ freqPolPos = 0 ;
244+ lookPos = 1 ;
245+ yDimPos = 2 ;
246+ xDimPos = 3 ;
247+ }
248+ if (arrayInfo .freqIdx >= 0 ) {
249+ origin [lookPos ] = arrayInfo .lookIdx ;
250+ origin [freqPolPos ] = arrayInfo .freqIdx ;
251+ shape [lookPos ] = 1 ;
252+ shape [freqPolPos ] = 1 ;
253+ } else {
254+ origin [freqPolPos ] = arrayInfo .polIdx ;
255+ origin [lookPos ] = arrayInfo .lookIdx ;
256+ shape [freqPolPos ] = 1 ;
257+ shape [lookPos ] = 1 ;
258+ }
259+ if (isWindowInside ) {
260+ origin [xDimPos ] = offsetX ;
261+ origin [yDimPos ] = offsetY ;
262+ shape [xDimPos ] = winWith ;
263+ shape [yDimPos ] = winHeight ;
264+ return variable .read (origin , shape ).reduce ();
265+ } else {
266+ final Rectangle2D insideWindow = RawDataReader .getInsideWindow (offsetX , offsetY , winWith , winHeight , productWidth , productHeight );
267+ origin [xDimPos ] = (int ) insideWindow .getX ();
268+ origin [yDimPos ] = (int ) insideWindow .getY ();
269+ shape [xDimPos ] = (int ) insideWindow .getWidth ();
270+ shape [yDimPos ] = (int ) insideWindow .getHeight ();
271+ final Array insideRead = variable .read (origin , shape ).reduce ();
272+ final Number fillValue = NetCDFUtils .getFillValue (variable );
273+ final Array array = NetCDFUtils .create (insideRead .getDataType (), new int []{winHeight , winWith }, fillValue );
274+ final int targetOffsY = Math .min (offsetY , 0 );
275+ final int targetOffsX = Math .min (offsetX , 0 );
276+ PartialDataCopier .copy (new int []{targetOffsY , targetOffsX }, insideRead , array );
277+ return array ;
235278 }
236- return fillValue ;
237279 }
238280
239281 @ Override
@@ -245,8 +287,10 @@ public Array readScaled(int centerX, int centerY, Interval interval, String vari
245287 }
246288
247289 final ArrayInfo arrayInfo = extractArrayInfo (variableName );
248- final double scaleFactor = arrayCache .getNumberAttributeValue ("scale_factor" , arrayInfo .ncVarName ).doubleValue ();
249- final double offset = arrayCache .getNumberAttributeValue ("add_offset" , arrayInfo .ncVarName ).doubleValue ();
290+ final Variable variable = netcdfFile .findVariable (arrayInfo .ncVarName );
291+ final AttributeContainer attributes = variable .attributes ();
292+ final double scaleFactor = attributes .findAttributeDouble ("scale_factor" , 1.0 );
293+ final double offset = attributes .findAttributeDouble ("add_offset" , 0.0 );
250294 final MAMath .ScaleOffset scaleOffset = new MAMath .ScaleOffset (scaleFactor , offset );
251295 return MAMath .convert2Unpacked (rawArray , scaleOffset );
252296 }
@@ -281,10 +325,14 @@ public List<Variable> getVariables() throws InvalidRangeException, IOException {
281325
282326 @ Override
283327 public Dimension getProductSize () throws IOException {
284- final Array longitudes = arrayCache . get ( "longitude" ) ;
285- final int [] shape = longitudes . getShape ();
328+ return productSize ;
329+ }
286330
287- return new Dimension ("size" , shape [1 ], shape [0 ]);
331+ public void initProductSize () {
332+ final int [] shape = netcdfFile .findVariable ("longitude" ).getShape ();
333+ productWidth = shape [1 ];
334+ productHeight = shape [0 ];
335+ productSize = new Dimension ("size" , productWidth , productHeight );
288336 }
289337
290338 @ Override
0 commit comments