HIMAWARI Asia–Oceania wide-area data. Its 3000 × 3000 grid is used as the main example on this page.
Satellite collections
Switch tabs to view the observation domain, grid, time interval, naming convention, and products for each satellite collection.
Overview of the HIMAWARI data
The values for the grid shown below are stored sequentially in the .bin file. Each cell has corresponding coordinates in separate lat and lng files with the same array shape. See Latitude and longitude files for filenames and usage.
A 1 km Japan-domain product on a 3001 × 2521 grid.
Japan-domain data corresponding to the satellite’s 2.5-minute scans.
Asia–Oceania wide-area data
fld.4km: 85°E to 155°W, 60°N to 60°S, 3000 × 3000 cells.Coordinate mapping: Use the lat and lng files with the same array shape as the data file. See Latitude and longitude files for filenames and usage.
fld.4km downward-shortwave-flux quicklook. The right panel explains the element code, observation time, unit, display range, grid dimensions, and color scale.Japan-domain data
msm.1km and 2.5-minute jp01.1km–jp04.1km; 120–150°E, 47.6–22.4°N, 3001 × 2521 cells.Coordinate mapping: msm.1km and jp01.1km–jp04.1km share the same Japan-domain grid. Use the lat and lng files with the same array shape. See Latitude and longitude files.
msm.1km downward-shortwave-flux quicklook. A 3001 × 2521 grid is produced every 10 minutes.
jp01.1km quicklook is shown as an example. The right panel explains that jp01 through jp04 correspond to offsets of 0, 2.5, 5, and 7.5 minutes from the same nominal time.Overview of the METEOSAT-IODC data
A collection covering the Indian Ocean domain. It uses a 0.03° grid with 4000 × 4000 cells at 15-minute intervals; the filename domain/resolution suffix is fld.3km. Coordinates are supplied in matching lat and lng files. See Latitude and longitude files.
A 4000 × 4000 grid. Cell centers extend from 59.985°N to 59.985°S and from 17.485°W to 102.485°E.
fld.3km: 17.5°W to 102.5°E, 60°N to 60°S, 4000 × 4000 cells.Coordinate mapping: Use the METEOSAT-IODC-specific lat and lng files with the same array shape as the data file. See Latitude and longitude files.
fld.3km downward-shortwave-flux quicklook. The right panel explains the element code, observation time, unit, display range, grid dimensions, and color scale.HIMAWARIMETEOSAT-IODC: Start with solar radiation
Solar radiation, the most widely used AMATERASS product, is used to explain the data from meaning to file access.
HIMAWARI collection — The 3000 × 3000 Asia–Oceania wide-area grid is the main example, followed by the Japan domain and its 2.5-minute products.
METEOSAT-IODC collection — The 4000 × 4000 Indian Ocean domain fld.3km is used as the main example.
Solar-radiation products
Downward shortwave flux at the surface (global irradiance)
Downward shortwave radiation reaching the surface: the sum of direct and diffuse components.
W/m²Direct solar irradiance at the surface
The shortwave component arriving directly from the direction of the Sun.
W/m²Diffuse solar irradiance at the surface
The shortwave component reaching the surface after scattering by the atmosphere and clouds.
W/m²Downward shortwave flux at the top of atmosphere
Downward shortwave radiation at the top of the atmosphere (TOA).
W/m²How to read a filename
HIMAWARI uses the 3000 × 3000 Asia–Oceania 4 km downward shortwave flux at the surface as the representative example.
METEOSAT-IODC uses the 4000 × 4000 Indian Ocean 3 km downward shortwave flux at the surface as the representative example.
YYYYMMDDHHMN (year, month, day, hour, minute).2023-07-13 02:00 UTC
Downward shortwave flux at the surface
Asia–Oceania wide area
YYYY = year, MM = month, DD = day, HH = hour, MN = minute (UTC)
Solar-radiation filename examples
202307130200.dwn.sw.flx.sfc.fld.4km.bin202307130200.dwn.sw.flx.sfc.tdir.fld.4km.bin202307130200.dwn.sw.flx.sfc.scat.fld.4km.bin202307130200.dwn.sw.flx.toa.fld.4km.binA .bin.png file, formed by appending .png to the binary filename, is a quicklook for visual inspection. Use the .bin file for numerical analysis.
2026-07-13 09:12 UTC
Downward shortwave flux at the surface
Indian Ocean domain
YYYY = year, MM = month, DD = day, HH = hour, MN = minute (UTC)
Solar-radiation filename examples
202607130912.dwn.sw.flx.sfc.fld.3km.bin202607130912.dwn.sw.flx.sfc.tdir.fld.3km.bin202607130912.dwn.sw.flx.sfc.scat.fld.3km.bin202607130912.dwn.sw.flx.toa.fld.3km.binA .bin.png file, formed by appending .png to the binary filename, is a quicklook for visual inspection. Use the .bin file for numerical analysis.
Binary format and storage order
202307130200.dwn.sw.flx.sfc.fld.4km.bin is used to illustrate the numeric representation and two-dimensional storage order.
202607130912.dwn.sw.flx.sfc.fld.3km.bin is used to illustrate the numeric representation and two-dimensional storage order.
fld.4km has 3000 × 3000 cells: 3000 × 3000 × 4 bytes = 36,000,000 bytes .The actual fld.3km has 4000 × 4000 cells: 4000 × 4000 × 4 bytes = 64,000,000 bytes . index = row × NX + columnLatitude and longitude files
Each domain has a latitude file (lat) and longitude file (lng) in one-to-one correspondence with the data grid. Both are headerless, Big-endian IEEE 754 Float32 (4 bytes per value). They use the same shape and storage order as the data file, so data, latitude, and longitude at the same [row, column] refer to the same grid cell.
| Collection | Coordinate files | Array shape (row, column) | Grid-cell-center coordinates | One file |
|---|---|---|---|---|
| HIMAWARI Asia–Oceania wide area | standard_3000x3000.lat.fld.4km.binstandard_3000x3000.lng.fld.4km.bin | 3000 × 3000 | Latitude: 59.98 → −59.98° Longitude: 85.02 → 204.98°E Increment: 0.04° | 36,000,000 bytes |
| HIMAWARI Japan domain | standard_2521x3001.lat.msm.1km.binstandard_2521x3001.lng.msm.1km.bin | 2521 × 3001 | Latitude: 47.595 → 22.395°N Longitude: 119.995 → 149.995°E Increment: 0.01° | 30,262,084 bytes |
| METEOSAT-IODC Indian Ocean domain | standard_4000x4000.iodc.42.5.lat.fld.3km.binstandard_4000x4000.iodc.42.5.lng.fld.3km.bin | 4000 × 4000 | Latitude: 59.985 → −59.985° Longitude: 342.515 → 102.485°E (wraps at 360°) = 17.485°W → 102.485°E Increment: 0.03° | 64,000,000 bytes |
The coordinates above aregrid-cell centers, not domain boundaries. The data are row-major: each row runs west to east and rows proceed north to south.
Per-pixel observation-time files
For Himawari-8 and Himawari-9, the actual observation time differs by pixel within a nominal image because the satellite scans the disk.A time file with the same grid as the data is supplied to represent this difference. This file is not part of the METEOSAT-IODC collection.
| Item | Specification |
|---|---|
| Element code | grd.time.mjd.hms |
| Numeric type | IEEE 754 Float32 (4 bytes per value) |
| Byte order | Big-endian |
| Header | None |
| Grid shape and storage order | Identical to the corresponding data, latitude, and longitude files |
| Distribution compression | bzip2 (.bz2); the decompressed file is the .bin binary payload |
| Unit of grid values | days (1 day = 1.0; 1 second = 1/86400 day) |
mjd.hms Despite the name, each grid value is not a complete MJD. It stores elapsed time in days from 00:00 UTC on the date in the filename.
| Domain | Time filename | Array shape | Decompressed size | Temporal structure |
|---|---|---|---|---|
| Asia–Oceania wide area | …grd.time.mjd.hms.fld.4km.bin | 3000 × 3000 | 36,000,000 bytes | Every 10 minutes |
| Japan domain | …grd.time.mjd.hms.msm.1km.bin | 2521 × 3001 | 30,262,084 bytes | Every 10 minutes |
| Japan high-frequency domain | …grd.time.mjd.hms.jp01.1km.binthrough …jp04.1km.bin | 2521 × 3001 | 30,262,084 bytes each | Four scans per nominal 10-minute time (2.5-minute intervals) |
Procedure
bzip2 -dkor an equivalent command to.bz2.- Read the time file as Big-endian Float32 using the same array shape as the data file.
- Associate the data value,
lat,lng, andtimeat the same[row, column]. - Use the equation above to convert the pixel value to its actual UTC date and time.
The coordinates above aregrid-cell centers, not domain boundaries. The data are row-major: each row runs west to east and rows proceed north to south.Longitudes use the 0–360° convention, beginning at 342.515°E (= 17.485°W), crossing 0°, and ending at 102.485°E.
Reader examples
Read 202307130200.dwn.sw.flx.sfc.fld.4km.bin (3000 × 3000 grid), with examples listed by language.
Read 202607130912.dwn.sw.flx.sfc.fld.3km.bin (4000 × 4000 grid), with examples listed by language.
Languages suited to sustained high-volume processing are listed first. Every example treats the first pixel as [1][1] and uses the same indices for data, latitude, longitude, and time.
Java: HIMAWARI fld.4km Click to expand source
HIMAWARI fld.4km specific The first pixel uses one-based indices, and data and coordinates are matched at identical indices.
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
/** AMATERASS HIMAWARI fld.4km reader. Arrays are intentionally one-based: the first pixel is [1][1]. */
public final class AmaterassPickup {
private static final int NX = 3000;
private static final int NY = 3000;
private static final long EXPECTED_BYTES = (long) NX * NY * Float.BYTES;
public static void main(String[] args) throws IOException {
if (args.length != 6) {
System.err.println("Usage: java -Xmx512m AmaterassPickup DATA.bin LAT.bin LNG.bin TIME.bin LATITUDE LONGITUDE");
System.exit(1);
}
float[][] data = readGrid(Path.of(args[0]));
float[][] lat = readGrid(Path.of(args[1]));
float[][] lon = readGrid(Path.of(args[2]));
float[][] time = readGrid(Path.of(args[3]));
double targetLat = Double.parseDouble(args[4]);
double targetLon = normalizeLon(Double.parseDouble(args[5]));
Pixel p = nearest(lat, lon, targetLat, targetLon);
System.out.printf("pixel = [%d][%d]%n", p.row, p.column);
System.out.printf("latitude = %.6f deg%n", lat[p.row][p.column]);
System.out.printf("longitude = %.6f deg%n", lon[p.row][p.column]);
System.out.printf("solar flux = %.3f W/m^2%n", data[p.row][p.column]);
double elapsedSeconds = time[p.row][p.column] * 86400.0;
System.out.printf("elapsed UTC seconds from filename date 00:00 = %.3f%n", elapsedSeconds);
}
private static float[][] readGrid(Path file) throws IOException {
if (Files.size(file) != EXPECTED_BYTES) throw new IOException("Unexpected file size: " + file);
float[][] grid = new float[NY + 1][NX + 1]; // index 0 is unused
ByteBuffer bytes = ByteBuffer.allocateDirect(NX * Float.BYTES).order(ByteOrder.BIG_ENDIAN);
try (FileChannel channel = FileChannel.open(file, StandardOpenOption.READ)) {
for (int row = 1; row <= NY; row++) {
bytes.clear();
while (bytes.hasRemaining()) if (channel.read(bytes) < 0) throw new EOFException(file.toString());
bytes.flip();
FloatBuffer values = bytes.asFloatBuffer();
values.get(grid[row], 1, NX);
}
}
return grid;
}
private static Pixel nearest(float[][] lat, float[][] lon, double targetLat, double targetLon) {
int bestRow = 1, bestColumn = 1;
double best = Double.POSITIVE_INFINITY;
for (int row = 1; row <= NY; row++) for (int column = 1; column <= NX; column++) {
double dLat = lat[row][column] - targetLat;
double dLon = Math.abs(normalizeLon(lon[row][column]) - targetLon);
dLon = Math.min(dLon, 360.0 - dLon);
double d2 = dLat * dLat + dLon * dLon;
if (d2 < best) { best = d2; bestRow = row; bestColumn = column; }
}
return new Pixel(bestRow, bestColumn);
}
private static double normalizeLon(double lon) {
double value = lon % 360.0;
return value < 0.0 ? value + 360.0 : value;
}
private record Pixel(int row, int column) {}
}
Java: METEOSAT-IODC fld.3km Click to expand source
METEOSAT-IODC fld.3km specific The first pixel uses one-based indices, and data and coordinates are matched at identical indices.
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
/** AMATERASS METEOSAT-IODC fld.3km reader. Arrays are intentionally one-based: the first pixel is [1][1]. */
public final class AmaterassPickupIodc {
private static final int NX = 4000;
private static final int NY = 4000;
private static final long EXPECTED_BYTES = (long) NX * NY * Float.BYTES;
public static void main(String[] args) throws IOException {
if (args.length != 5) {
System.err.println("Usage: java -Xmx512m AmaterassPickupIodc DATA.bin LAT.bin LNG.bin LATITUDE LONGITUDE");
System.exit(1);
}
float[][] data = readGrid(Path.of(args[0]));
float[][] lat = readGrid(Path.of(args[1]));
float[][] lon = readGrid(Path.of(args[2]));
double targetLat = Double.parseDouble(args[3]);
double targetLon = normalizeLon(Double.parseDouble(args[4]));
Pixel p = nearest(lat, lon, targetLat, targetLon);
System.out.printf("pixel = [%d][%d]%n", p.row, p.column);
System.out.printf("latitude = %.6f deg%n", lat[p.row][p.column]);
System.out.printf("longitude = %.6f deg%n", lon[p.row][p.column]);
System.out.printf("solar flux = %.3f W/m^2%n", data[p.row][p.column]);
}
private static float[][] readGrid(Path file) throws IOException {
if (Files.size(file) != EXPECTED_BYTES) throw new IOException("Unexpected file size: " + file);
float[][] grid = new float[NY + 1][NX + 1]; // index 0 is unused
ByteBuffer bytes = ByteBuffer.allocateDirect(NX * Float.BYTES).order(ByteOrder.BIG_ENDIAN);
try (FileChannel channel = FileChannel.open(file, StandardOpenOption.READ)) {
for (int row = 1; row <= NY; row++) {
bytes.clear();
while (bytes.hasRemaining()) if (channel.read(bytes) < 0) throw new EOFException(file.toString());
bytes.flip();
FloatBuffer values = bytes.asFloatBuffer();
values.get(grid[row], 1, NX);
}
}
return grid;
}
private static Pixel nearest(float[][] lat, float[][] lon, double targetLat, double targetLon) {
int bestRow = 1, bestColumn = 1;
double best = Double.POSITIVE_INFINITY;
for (int row = 1; row <= NY; row++) for (int column = 1; column <= NX; column++) {
double dLat = lat[row][column] - targetLat;
double dLon = Math.abs(normalizeLon(lon[row][column]) - targetLon);
dLon = Math.min(dLon, 360.0 - dLon);
double d2 = dLat * dLat + dLon * dLon;
if (d2 < best) { best = d2; bestRow = row; bestColumn = column; }
}
return new Pixel(bestRow, bestColumn);
}
private static double normalizeLon(double lon) {
double value = lon % 360.0;
return value < 0.0 ? value + 360.0 : value;
}
private record Pixel(int row, int column) {}
}
C: HIMAWARI fld.4km Click to expand source
HIMAWARI fld.4km specific The first pixel uses one-based indices, and data and coordinates are matched at identical indices.
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define NX 3000
#define NY 3000
typedef float (*Grid)[NX + 1];
/* Index 0 is intentionally unused; the first pixel is grid[1][1]. */
static int little_endian(void) { const uint16_t x = 1; return *(const uint8_t *)&x; }
static float swap_float(float value) {
union { float f; uint8_t b[4]; } in = { .f = value }, out;
out.b[0]=in.b[3]; out.b[1]=in.b[2]; out.b[2]=in.b[1]; out.b[3]=in.b[0];
return out.f;
}
static Grid read_grid(const char *name) {
FILE *fp = fopen(name, "rb");
Grid grid = calloc(NY + 1, sizeof *grid);
if (!fp || !grid) { perror(name); exit(EXIT_FAILURE); }
for (int row = 1; row <= NY; row++) {
if (fread(&grid[row][1], sizeof(float), NX, fp) != NX) { fprintf(stderr, "Short file: %s\n", name); exit(EXIT_FAILURE); }
if (little_endian()) for (int column = 1; column <= NX; column++) grid[row][column] = swap_float(grid[row][column]);
}
if (fgetc(fp) != EOF) { fprintf(stderr, "File is larger than expected: %s\n", name); exit(EXIT_FAILURE); }
fclose(fp); return grid;
}
static double norm_lon(double x) { x = fmod(x, 360.0); return x < 0 ? x + 360.0 : x; }
int main(int argc, char **argv) {
if (argc != 7) { fprintf(stderr, "Usage: %s DATA.bin LAT.bin LNG.bin TIME.bin LATITUDE LONGITUDE\n", argv[0]); return EXIT_FAILURE; }
Grid data = read_grid(argv[1]);
Grid lat = read_grid(argv[2]);
Grid lon = read_grid(argv[3]);
Grid time = read_grid(argv[4]);
double target_lat = strtod(argv[5], NULL), target_lon = norm_lon(strtod(argv[6], NULL));
int best_row = 1, best_column = 1; double best = HUGE_VAL;
for (int row = 1; row <= NY; row++) for (int column = 1; column <= NX; column++) {
double dlat = lat[row][column] - target_lat;
double dlon = fabs(norm_lon(lon[row][column]) - target_lon); dlon = fmin(dlon, 360.0 - dlon);
double d2 = dlat*dlat + dlon*dlon;
if (d2 < best) { best=d2; best_row=row; best_column=column; }
}
int row=best_row, column=best_column;
printf("pixel = [%d][%d]\n", row, column);
printf("latitude = %.6f deg\n", lat[row][column]);
printf("longitude = %.6f deg\n", lon[row][column]);
printf("solar flux = %.3f W/m^2\n", data[row][column]);
printf("elapsed UTC seconds from filename date 00:00 = %.3f\n", (double)time[row][column] * 86400.0);
free(data); free(lat); free(lon); free(time);
return EXIT_SUCCESS;
}
C: METEOSAT-IODC fld.3km Click to expand source
METEOSAT-IODC fld.3km specific The first pixel uses one-based indices, and data and coordinates are matched at identical indices.
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define NX 4000
#define NY 4000
typedef float (*Grid)[NX + 1];
/* Index 0 is intentionally unused; the first pixel is grid[1][1]. */
static int little_endian(void) { const uint16_t x = 1; return *(const uint8_t *)&x; }
static float swap_float(float value) {
union { float f; uint8_t b[4]; } in = { .f = value }, out;
out.b[0]=in.b[3]; out.b[1]=in.b[2]; out.b[2]=in.b[1]; out.b[3]=in.b[0];
return out.f;
}
static Grid read_grid(const char *name) {
FILE *fp = fopen(name, "rb");
Grid grid = calloc(NY + 1, sizeof *grid);
if (!fp || !grid) { perror(name); exit(EXIT_FAILURE); }
for (int row = 1; row <= NY; row++) {
if (fread(&grid[row][1], sizeof(float), NX, fp) != NX) { fprintf(stderr, "Short file: %s\n", name); exit(EXIT_FAILURE); }
if (little_endian()) for (int column = 1; column <= NX; column++) grid[row][column] = swap_float(grid[row][column]);
}
if (fgetc(fp) != EOF) { fprintf(stderr, "File is larger than expected: %s\n", name); exit(EXIT_FAILURE); }
fclose(fp); return grid;
}
static double norm_lon(double x) { x = fmod(x, 360.0); return x < 0 ? x + 360.0 : x; }
int main(int argc, char **argv) {
if (argc != 6) { fprintf(stderr, "Usage: %s DATA.bin LAT.bin LNG.bin LATITUDE LONGITUDE\n", argv[0]); return EXIT_FAILURE; }
Grid data = read_grid(argv[1]);
Grid lat = read_grid(argv[2]);
Grid lon = read_grid(argv[3]);
double target_lat = strtod(argv[4], NULL), target_lon = norm_lon(strtod(argv[5], NULL));
int best_row = 1, best_column = 1; double best = HUGE_VAL;
for (int row = 1; row <= NY; row++) for (int column = 1; column <= NX; column++) {
double dlat = lat[row][column] - target_lat;
double dlon = fabs(norm_lon(lon[row][column]) - target_lon); dlon = fmin(dlon, 360.0 - dlon);
double d2 = dlat*dlat + dlon*dlon;
if (d2 < best) { best=d2; best_row=row; best_column=column; }
}
int row=best_row, column=best_column;
printf("pixel = [%d][%d]\n", row, column);
printf("latitude = %.6f deg\n", lat[row][column]);
printf("longitude = %.6f deg\n", lon[row][column]);
printf("solar flux = %.3f W/m^2\n", data[row][column]);
free(data); free(lat); free(lon); return EXIT_SUCCESS;
}
Fortran: HIMAWARI fld.4km Click to expand source
HIMAWARI fld.4km specific The first pixel uses one-based indices, and data and coordinates are matched at identical indices.
program amaterass_pickup
use iso_fortran_env, only: real32, real64, error_unit
implicit none
integer, parameter :: NX=3000, NY=3000
real(real32), allocatable :: data(:,:), lat(:,:), lon(:,:), time
character(len=1024) :: arg(6)
integer :: i, row, col, best_row, best_col
real(real64) :: target_lat, target_lon, dlat, dlon, d2, best
! Fortran arrays are naturally one-based; the first pixel is (1,1).
if (command_argument_count() /= 6) error stop 'Invalid number of arguments'
do i=1,6; call get_command_argument(i,arg(i)); end do
allocate(data(NY,NX), lat(NY,NX), lon(NY,NX), time(NY,NX))
call read_grid(trim(arg(1)), data)
call read_grid(trim(arg(2)), lat)
call read_grid(trim(arg(3)), lon)
call read_grid(trim(arg(4)), time)
read(arg(5),*) target_lat; read(arg(6),*) target_lon
target_lon = modulo(target_lon,360.0_real64)
best=huge(best); best_row=1; best_col=1
do row=1,NY
do col=1,NX
dlat=real(lat(row,col),real64)-target_lat
dlon=abs(modulo(real(lon(row,col),real64),360.0_real64)-target_lon); dlon=min(dlon,360.0_real64-dlon)
d2=dlat*dlat+dlon*dlon
if (d2<best) then; best=d2; best_row=row; best_col=col; end if
end do
end do
print '(A,I0,A,I0,A)', 'pixel = [',best_row,'][',best_col,']'
print '(A,F12.6)', 'latitude = ',lat(best_row,best_col)
print '(A,F12.6)', 'longitude = ',lon(best_row,best_col)
print '(A,F12.3)', 'solar flux = ',data(best_row,best_col)
print '(A,F12.3)', 'elapsed UTC seconds from filename date 00:00 = ', real(time(best_row,best_col),real64)*86400.0_real64
contains
subroutine read_grid(name,grid)
character(len=*),intent(in)::name
real(real32),intent(out)::grid(NY,NX)
real(real32)::row_values(NX)
integer::u,r,stat
open(newunit=u,file=name,access='stream',form='unformatted',status='old',action='read',convert='big_endian')
do r=1,NY
read(u,iostat=stat) row_values
if(stat/=0) error stop 'Unexpected end of file'
grid(r,1:NX)=row_values
end do
close(u)
end subroutine
end program
Fortran: METEOSAT-IODC fld.3km Click to expand source
METEOSAT-IODC fld.3km specific The first pixel uses one-based indices, and data and coordinates are matched at identical indices.
program amaterass_pickup_iodc
use iso_fortran_env, only: real32, real64, error_unit
implicit none
integer, parameter :: NX=4000, NY=4000
real(real32), allocatable :: data(:,:), lat(:,:), lon(:,:)
character(len=1024) :: arg(5)
integer :: i, row, col, best_row, best_col
real(real64) :: target_lat, target_lon, dlat, dlon, d2, best
! Fortran arrays are naturally one-based; the first pixel is (1,1).
if (command_argument_count() /= 5) error stop 'Invalid number of arguments'
do i=1,5; call get_command_argument(i,arg(i)); end do
allocate(data(NY,NX), lat(NY,NX), lon(NY,NX))
call read_grid(trim(arg(1)), data)
call read_grid(trim(arg(2)), lat)
call read_grid(trim(arg(3)), lon)
read(arg(4),*) target_lat; read(arg(5),*) target_lon
target_lon = modulo(target_lon,360.0_real64)
best=huge(best); best_row=1; best_col=1
do row=1,NY
do col=1,NX
dlat=real(lat(row,col),real64)-target_lat
dlon=abs(modulo(real(lon(row,col),real64),360.0_real64)-target_lon); dlon=min(dlon,360.0_real64-dlon)
d2=dlat*dlat+dlon*dlon
if (d2<best) then; best=d2; best_row=row; best_col=col; end if
end do
end do
print '(A,I0,A,I0,A)', 'pixel = [',best_row,'][',best_col,']'
print '(A,F12.6)', 'latitude = ',lat(best_row,best_col)
print '(A,F12.6)', 'longitude = ',lon(best_row,best_col)
print '(A,F12.3)', 'solar flux = ',data(best_row,best_col)
contains
subroutine read_grid(name,grid)
character(len=*),intent(in)::name
real(real32),intent(out)::grid(NY,NX)
real(real32)::row_values(NX)
integer::u,r,stat
open(newunit=u,file=name,access='stream',form='unformatted',status='old',action='read',convert='big_endian')
do r=1,NY
read(u,iostat=stat) row_values
if(stat/=0) error stop 'Unexpected end of file'
grid(r,1:NX)=row_values
end do
close(u)
end subroutine
end program
Python: HIMAWARI fld.4km Click to expand source
HIMAWARI fld.4km specific The first pixel uses one-based indices, and data and coordinates are matched at identical indices.
from pathlib import Path
import sys
import numpy as np
NX, NY = 3000, 3000
def read_grid(path: Path) -> np.ndarray:
raw = np.fromfile(path, dtype=">f4")
if raw.size != NX * NY:
raise ValueError(f"unexpected size: {path} ({raw.size} values)")
grid = np.empty((NY + 1, NX + 1), dtype=np.float32)
grid[0, :] = np.nan; grid[:, 0] = np.nan
grid[1:, 1:] = raw.reshape(NY, NX)
return grid
def main() -> None:
# Index 0 is intentionally unused; the first pixel is grid[1, 1].
if len(sys.argv) != 7:
raise SystemExit("invalid number of arguments")
data = read_grid(Path(sys.argv[1]))
lat = read_grid(Path(sys.argv[2]))
lon = read_grid(Path(sys.argv[3]))
time = read_grid(Path(sys.argv[4]))
target_lat = float(sys.argv[5]); target_lon = float(sys.argv[6]) % 360.0
dlat = lat[1:, 1:] - target_lat
dlon = np.abs(np.mod(lon[1:, 1:], 360.0) - target_lon); dlon = np.minimum(dlon, 360.0 - dlon)
flat = int(np.nanargmin(dlat*dlat + dlon*dlon))
row0, col0 = np.unravel_index(flat, (NY, NX)); row, column = row0 + 1, col0 + 1
print(f"pixel = [{row}][{column}]")
print(f"latitude = {lat[row, column]:.6f} deg")
print(f"longitude = {lon[row, column]:.6f} deg")
print(f"solar flux = {data[row, column]:.3f} W/m^2")
print(f"elapsed UTC seconds from filename date 00:00 = {float(time[row, column]) * 86400.0:.3f}")
if __name__ == "__main__":
main()
Python: METEOSAT-IODC fld.3km Click to expand source
METEOSAT-IODC fld.3km specific The first pixel uses one-based indices, and data and coordinates are matched at identical indices.
from pathlib import Path
import sys
import numpy as np
NX, NY = 4000, 4000
def read_grid(path: Path) -> np.ndarray:
raw = np.fromfile(path, dtype=">f4")
if raw.size != NX * NY:
raise ValueError(f"unexpected size: {path} ({raw.size} values)")
grid = np.empty((NY + 1, NX + 1), dtype=np.float32)
grid[0, :] = np.nan; grid[:, 0] = np.nan
grid[1:, 1:] = raw.reshape(NY, NX)
return grid
def main() -> None:
# Index 0 is intentionally unused; the first pixel is grid[1, 1].
if len(sys.argv) != 6:
raise SystemExit("invalid number of arguments")
data = read_grid(Path(sys.argv[1]))
lat = read_grid(Path(sys.argv[2]))
lon = read_grid(Path(sys.argv[3]))
target_lat = float(sys.argv[4]); target_lon = float(sys.argv[5]) % 360.0
dlat = lat[1:, 1:] - target_lat
dlon = np.abs(np.mod(lon[1:, 1:], 360.0) - target_lon); dlon = np.minimum(dlon, 360.0 - dlon)
flat = int(np.nanargmin(dlat*dlat + dlon*dlon))
row0, col0 = np.unravel_index(flat, (NY, NX)); row, column = row0 + 1, col0 + 1
print(f"pixel = [{row}][{column}]")
print(f"latitude = {lat[row, column]:.6f} deg")
print(f"longitude = {lon[row, column]:.6f} deg")
print(f"solar flux = {data[row, column]:.3f} W/m^2")
if __name__ == "__main__":
main()
High-volume processing: The Python example assumes vectorized NumPy input. Avoid pure-Python pixel loops; Java, C, or Fortran is recommended for sustained processing across long periods and many time steps.
HIMAWARIMETEOSAT-IODC: Other products
Additional derived products are listed separately for each satellite collection.
Derived, cloud, and surface-meteorology products
| Category | Product | Element code | Unit |
|---|---|---|---|
| Photovoltaics | Estimated PV output per 1 kWp | unit.pvp.tc028.ac000.sfcunit.pvp.tc028.ac945.sfcunit.pvp.tc028.ac975.sfcunit.pvp.tc049.ac000.sfcunit.pvp.tc049.ac945.sfcunit.pvp.tc049.ac975.sfc | kW/kWp |
| Photovoltaics | Estimated PV-panel temperature used in the power calculation | noct | K |
| Cloud | Cloud optical thickness (liquid-water-cloud assumption) | wtr.cld.tau | dimensionless |
| Cloud | Cloud optical thickness (ice-cloud assumption) | ice.cld.tau | dimensionless |
| Cloud | Cloud optical thickness (cloud phase based on brightness temperature) | wi.cld.tau | dimensionless |
| Cloud | Cloud-top height | wtr.cld.cth | km |
| Cloud | Cloud-top pressure | wtr.cld.ctp | hPa |
| Cloud | Cloud-top temperature | wtr.cld.ctt | K |
| Cloud | Cloud-particle effective radius | wtr.cld.eff | µm |
| Cloud | Cloud liquid water path | wtr.cld.lwp | g/m² |
| Infrared difference | 10.4 µm-12.3 µm brightness-temperature difference | btd.tir1-tir3.tbb | K |
| Infrared difference | 8.6 µm-11.2 µm brightness-temperature difference | btd.tir9-tir2.tbb | K |
| Infrared difference | 8.6 µm-12.3 µm brightness-temperature difference | btd.tir9-tir3.tbb | K |
| Surface meteorology | Surface relative humidity | rh.sfc | % |
| Surface meteorology | Surface air temperature | tsfc | K |
| Surface meteorology | Surface wind speed | wnd.spd.sfc | m/s |
The collection contains 25 products: four solar-radiation, seven PV-related, eight cloud, three infrared brightness-temperature-difference, and three surface-meteorology products. The three surface-meteorology products are available for fld.4km and msm.1km; the other 22 products are available for fld.4km, msm.1km, and jp01.1km through jp04.1km.
unit.pvp explained
unit.pvp represents the estimated output of a 1 kWp photovoltaic system. A value of 0.8 means an output of approximately 0.8 kW from 1 kWp at that time and grid cell.
unit.pvp.tc028.ac945.sfc = estimated PV output per 1 kWp [kW/kWp], calculated with a temperature coefficient of −0.28%/°C and inverter efficiency of 94.5%
tc049 is −0.49 %/°C; ac975 is 97.5%; ac000 represents the ideal 100% condition. The legacy code noct is not the nameplate Nominal Operating Cell Temperature; it is the estimated PV-panel temperature [K] used for the power calculation at each time and grid cell.
Photovoltaic output
| Category | Product | Element code | Unit |
|---|---|---|---|
| Photovoltaics | Estimated PV output per 1 kWp | unit.pvp.tc028.ac000.sfcunit.pvp.tc028.ac945.sfcunit.pvp.tc028.ac975.sfcunit.pvp.tc049.ac000.sfcunit.pvp.tc049.ac945.sfcunit.pvp.tc049.ac975.sfc | kW/kWp |
METEOSAT-IODC includes four solar-radiation products and six PV-output products formed from two temperature-coefficient settings (tc028 and tc049) and three inverter-efficiency settings (ac000, ac945, and ac975).
unit.pvp explained
unit.pvp is the estimated output of a 1 kWp photovoltaic system. For example, a value of 0.8 means approximately 0.8 kW/kWp at that time and grid cell.
unit.pvp.tc028.ac945.sfc.fld.3km.bin = estimated PV output per 1 kWp, calculated with a temperature coefficient of −0.28%/°C and inverter efficiency of 94.5%