-
Notifications
You must be signed in to change notification settings - Fork 1
/
image_id_identifier.html
320 lines (287 loc) · 14.7 KB
/
image_id_identifier.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title>PDS image Id identifier</title>
</head>
<body>
<!--
Extracts reference to XYZ products and texture to allow passing them to Blender Navcam Import plugin to generate 3d model.
v. 0.0.1 - First working version. To do: path to texture for existing XYZ products is not managed correctly (function aPath() )
-->
<h1>PDS image id identifier</h1><br>
<br>
Please insert filename or single data:<br>
<br>
Filename (13 characters): <input type = "text" id="txtFile" name="txtFile" value="2ppj11ilfb1cypdop2284r222m1" size = 30>
(example: <a href="https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2om_0xxx/browse/pancam/site0137/2ppj11ilfb1cypdop2284r222m1.img.jpg">2ppj11ilfb1cypdop2284r222m1</a> <button onclick="calcAndUrls()">Calc</button><br>
(<a href="https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2om_0xxx/browse/pancam/site0137">Example folder</a>) )
<br>
<br>
<img id="imgThumbnail" name="imgThumbnail" src=""><br>
Thumbnail url: <span id="thumbnail" name="thumbnail"></span><br>
Preview url: <span id="preview" name="preview"></span><br>
Product url: <span id="product" name="product"></span><br>
List of images used: <span id="list" name="list"></span><br>
Folder for single images: <span id="single" name="single"></span><br>
<br>
<button onclick="downloadFilesList(listUrl);">Download</button>Source files list:<br>
<textarea id="list2" name="list2" cols=50 rows= 20></textarea><br>
<br>
Check 3d data availability: <button onclick="check3d()">Execute</button><br>
<br>
Paste this list into Blender Navcam Importer plugin to create the 3d model:<br>
<span id="spnBlenderlist" name="spnXYZlist"></span><br>
<br>
Use following links to manually download XYZ products if available:<br>
<span id="spnXYZlist" name="spnXYZlist"></span><br>
<br>
Data:<br>
<button onclick="fillData()">Fill from filename</button><br>
Sol(*) (3 characters): <input type = "text" id="txtSol" name="txtSol" value="i69" size=4> <span id="solResult" name="solResult"></span><br>
Site (2 characters): <input type = "text" id="txtSite" name="txtSite" value="b1" size=3> <span id="siteResult" name="siteResult"></span><br>
Drive (2 characters): <input type = "text" id="txtDrive" name="txtDrive" value="zz" size=3> <span id="driveResult" name="driveResult"></span><br>
<button onclick="calculate()">Calc</button><br>
<br>
<br><hr><br>
From <a href="https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2om_0xxx/document/CAMSIS_latest.PDF">camsis.pdf</a>:<br>
<strong>sol</strong> = (3 alphanumeric) Starting Sol. Indicates the Sol of the first (in time order, the lowest SCLK)
mosaic chip, denoting the start of mosaic data acquisition. Example value is "004".<br>
The valid Sol values, in their progression, are as follows (non-Hex):<br>
Range 000 thru 999 - "000", "001", ... "999"<br>
Range 1000 thru 1099 - "A00", "A01", ... "A99"<br>
Range 1100 thru 1199 - "B00", "B01", ... "B99"<br>
Range 3500 thru 3599 - "Z00", "Z01", ... "Z99"<br>
Range 3600 thru 10359 - "AA0", "AA1" ... "AA9", "AB0", "AB1" ... "AB9", "ZA0", "ZA1" ... "ZA9", "ZB0" ... "ZZ9"<br>
Range 10360 thru 27935 - "AAA", "AAB" ... "AAZ", "ABA", "ABB" ... "ABZ", "ZZA", "ZZB" ... "ZZZ"<br>
Range 27936 or greater - "###" (3 pound signs) for Operations, or "___" (3 underscores) for Archive<br>
<br>
<strong>site</strong> = (2 alphanumeric) Site location count. Use of both integers and alphas allows for a total
range of 0 thru 1295. A value greater than 1295 is denoted by "##" (2 pound signs) for
Operations and by "__" (2 underscores) for Archive volumes, requiring the user to extract
actual value from label.<br>
The valid values, in their progression, are as follows:<br>
Range 0 thru 99 - "00", "01", "02"... "99"<br>
Range 100 thru 1035 - "A0", "A1" ... "A9", "AA", "AB"..."AZ", "B0", "B1"... "ZZ"<br>
Range 1036 thru 1295 - "0A", "0B ... "0Z", "1A", "1B"..."9Z"<br>
Range 1296 or greater - "##" (2 pound signs) for Operations, or "__" (2 underscores) for Archive<br>
Example value is "AK" for value of 120<br>
<br>
<strong>pos</strong> = (2 alphanumeric) Position-within-Site count. (see "site" above).<br>
<br>
(*) Only up to Z99 (3599)<br>
<!--<script src="https://unpkg.com/axios/dist/axios.min.js"></script>-->
<script src="downloader-lib.js"></script>
<script>
sourceFilesArr = [];
MIN_FILE_LENGTH = 27;
SPIRIT_TIMETABLE_FILE_URL = "https://github.com/jumpjack/VST-converter/raw/main/rover_location/timetable-spirit.tsv";
myValues ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
alphabet = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ";
thumbnailBaseUrlPancamSingle = "https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2po_0xxx/extras/thumbnail/";
previewBaseUrlPancamSingle = "https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2po_0xxx/browse/";
productBaseUrlPancamSingle = "https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2po_0xxx/data/";
thumbnailBaseUrlPancam = "https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2om_0xxx/extras/thumbnail/pancam/";
previewBaseUrlPancam = "https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2om_0xxx/browse/pancam/";
productBaseUrlPancam = "https://pds-imaging.jpl.nasa.gov/data/mer/spirit/mer2om_0xxx/data/pancam/";
function fillData() {
document.getElementById("txtSol").value = document.getElementById("txtFile").value.substr(3,3);
document.getElementById("txtSite").value = document.getElementById("txtFile").value.substr(9,2);
document.getElementById("txtDrive").value = document.getElementById("txtFile").value.substr(14,2);
}
function fillAndCalc() {
fillData();
calculate();
}
function zeroes(num, figures) {
num = num+"";
count = 0;
while (num.length<figures) {
count++;
num = "0" + num;
}
return num;
}
function calculate(){
solRaw=document.getElementById("txtSol").value;
siteRaw=document.getElementById("txtSite").value;
driveRaw=document.getElementById("txtDrive").value;
solRaw = solRaw.toUpperCase();
sol_1=solRaw[0];
sol_2=solRaw[1]*1;
sol_3=solRaw[2]*1;
solNum = myValues.indexOf(sol_1)*100 + sol_2*10 + sol_3;
solString = "sol"+zeroes(solNum,4);
console.log(solString);
console.log(previewBaseUrlPancam + solString + "/rdr/");
solResult.innerHTML = solNum;
siteRaw = siteRaw.toUpperCase();
site_1=siteRaw[0];
site_2=siteRaw[1];
if (myValues.indexOf(site_1) <= 9) {
siteNum = (site_1 + site_2)*1;
}
if (myValues.indexOf(site_1) > 9) {
siteNum = (alphabet.indexOf(site_1)-1)*36+100 + myValues.indexOf(site_2)*1;
}
siteString = "site" + zeroes(siteNum,4);
console.log(siteString);
siteResult.innerHTML = siteNum;
driveRaw = driveRaw.toUpperCase();
drive_1=driveRaw[0];
drive_2=driveRaw[1];
if (myValues.indexOf(drive_1) <= 9) {
driveNum = (drive_1 + drive_2)*1;
}
if (myValues.indexOf(drive_1) > 9) {
driveNum = (alphabet.indexOf(drive_1)-1)*36+100 + myValues.indexOf(drive_2)*1;
}
console.log(driveNum);
driveResult.innerHTML = driveNum;
}
function fillUrls() {
thumbnailFolderUrl = thumbnailBaseUrlPancam + siteString + "/";
previewFolderUrl = previewBaseUrlPancam + siteString + "/";
productFolderUrl = productBaseUrlPancam + siteString + "/";
thumbnailSingleFolderUrl = thumbnailBaseUrlPancamSingle + solString + "/rdr/";
previewSingleFolderUrl = previewBaseUrlPancamSingle + solString + "/rdr/";
productSingleFolderUrl = productBaseUrlPancamSingle + solString + "/rdr/";
thumbnailUrl = thumbnailFolderUrl + document.getElementById("txtFile").value + ".img.jpg";
previewUrl = previewFolderUrl + document.getElementById("txtFile").value + ".img.jpg";
productUrl = productFolderUrl + document.getElementById("txtFile").value + ".img";
listUrl = productFolderUrl + document.getElementById("txtFile").value + ".lis";
document.getElementById("thumbnail").innerHTML = '<a href="' + thumbnailUrl + '">JPG file</a> (<a href="' + thumbnailFolderUrl + '">folder</a>)';
document.getElementById("preview").innerHTML = '<a href="' + previewUrl + '">JPG file</a> (<a href="' + previewFolderUrl + '">folder</a>)';
document.getElementById("product").innerHTML = '<a href="' + productUrl + '">IMG file</a> (<a href="' + productFolderUrl + '">folder</a>)';
document.getElementById("list").innerHTML = '<a href="' + listUrl + '">LIS file</a> (<a href="' + productFolderUrl + '">folder</a>)';
document.getElementById("single").innerHTML = '<a href="' + thumbnailSingleFolderUrl + '">thumbnail</a>, <a href="' + previewSingleFolderUrl + '">preview</a>, <a href="' + productSingleFolderUrl + '">product</a>';
document.getElementById("imgThumbnail").src = thumbnailUrl;
}
function calcAndUrls() {
fillData();
calculate();
fillUrls();
}
async function downloadFilesList(listUrl) {
document.getElementById("list2").value = "";
if (await remoteFileExists(listUrl)) {
console.log("Ok, LIS file exists...");
LISfileContents = await retrieve(listUrl); // Download LIS file
if (LISfileContents.indexOf("\n") >= 0) {
console.log("Ok, LIS file not empty...");
// Extract list of images
sourceFilesList = LISfileContents.split("\n");
sourceFilesList.forEach((sourceFileRaw) => {
sourceFileArr = sourceFileRaw.split("/");
sourceFile = sourceFileArr[sourceFileArr.length-1]; // Last element is file name
if (sourceFile.length> MIN_FILE_LENGTH) {
//sourceFilesArr.push(sourceFile);
document.getElementById("list2").value += sourceFile + "\n";
}
});
console.log("Source images list retrieved.",sourceFilesList);
} else {
console.log("******** ERROR - Empty LIS file?!?");
}
} else {
console.log("ERROR, no LIS file at this url:", listUrl);
}
}
function cleanList() {
rawList = document.getElementById("list2").value;
fixedList = rawList.split('"').join("");
fixedList = fixedList.split(',').join("");
fixedList = fixedList.split(' ').join("");
fixedList = fixedList.split('\t').join("");
document.getElementById("list2").value = fixedList;
}
async function check3d() {
sourceFilesArr = document.getElementById("list2").value.split("\n");
console.log(">>>>", sourceFilesArr);
// Associate sol folder to SCLK value:
// For each image:
// Check 3d file existence (XYZ product with same SCLK and filter)
// If file exists, add marker, else delete marker
// Filename format: 2P131789123ILF1200P2440L7M1.IMG
// (Usually XYZ products are associated to "L7" product images)
// 2 = rover
// P = pancam
// 131789123 = SCLK (2..10, size = 9) <<<<<<<<=============
// ILF = product type; we have to look for "XYZ" instead
// 12 = site
// 00 = drive
// P2440 = sequence
// L = Left camera <<<<<<<<=============
// 7 = filter <<<<<<<<=============
// M = created by NASA MIPS
// 1 = Version 1 of product
//
// Have to look for 2P131789123XYZ*.img in SOLxxxx folder derived from 131789123
XYZlist = [];
document.getElementById("spnBlenderlist").innerHTML ="";
document.getElementById("spnXYZlist").innerHTML ="";
sourceFilesArr.forEach((sourceImage) => aPath(sourceImage) );
console.log(XYZlist);
}
async function aPath(sourceImage) {
imgRoverAndCam = sourceImage.substr(0,2);
imgSCLK = sourceImage.substr(2,9);
imgSCLKnum = imgSCLK * 1;
imgSiteDrive = sourceImage.substr(14,4);
imgSeq = sourceImage.substr(18,5);
XYZ_Data = await getImagePath(sourceImage); // Query official NASA API to figure out if and where XYZ products are available
XYZpath = XYZ_Data.fullPath;
XYZfolder = XYZ_Data.folderName;
XYZname = XYZ_Data.fileName;
console.log("Image =", sourceImage);
console.log("Product=", imgRoverAndCam + imgSCLK + "XYZ" + imgSiteDrive + imgSeq + "L7M1", "path=",XYZpath);
XYZlist.push({path: XYZpath});
document.getElementById("spnBlenderlist").innerHTML += XYZname + ',';
textureFullPath = XYZfolder.replace("data/sol","browse/sol") + sourceImage.toUpperCase().replace("EFF","FFL") + '.img.jpg';
textureFullPath = textureFullPath.toLowerCase();
if (XYZpath != "N/A") {
document.getElementById("spnXYZlist").innerHTML += '<a href="' + XYZpath + '">' +
XYZname +
'</a> (<a href="' +
XYZfolder +
'">folder</a>, <a href="' + textureFullPath +
'">texture</a>)<br>';
} else {
document.getElementById("spnXYZlist").innerHTML += sourceImage + ': N/A (<a href="' +
XYZfolder +
'">folder</a>, <a href="' + textureFullPath + // DEBUG: texture for not-found-XYZ not working
'">texture</a>)<br>';
}
}
async function getImagePath(textureName) {
chunk = textureName.substr(0,11) + "XYL";
// Query official NASA PDS API to figure out if and where XYZ products are available
var DOWNLOAD_URL = "https://pds-imaging.jpl.nasa.gov/data/mer/";
var QUERY_BASE_URL="https://pds-imaging.jpl.nasa.gov/solr/pds_archives/search?pds.FILE_NAME=";
var PARAMETERS = "*&pds.INSTRUMENT_HOST_ID=MERA/MER2/Spirit&pds.atlas_instrument_name=pancam&wt=json&rows=100&fl=FILE_NAME&fl=ATLAS_THUMBNAIL_URL&fl=FILE_PATH";
var url = QUERY_BASE_URL + chunk + PARAMETERS;
return new Promise(resolve => {
var xhr = new XMLHttpRequest();
xhr.open('GET', PROXY + encodeURIComponent(url), true);
xhr.onload = function(resp) {
var rawResponse = resp.currentTarget.response;
var queryResultJSON = JSON.parse(rawResponse);
if (queryResultJSON.response) {
if (queryResultJSON.response.docs) {
if (queryResultJSON.response.docs.length > 0) {
console.log("FOUND ",DOWNLOAD_URL + queryResultJSON.response.docs[0].FILE_PATH + queryResultJSON.response.docs[0].FILE_NAME)
resolve ({fullPath: DOWNLOAD_URL + queryResultJSON.response.docs[0].FILE_PATH + queryResultJSON.response.docs[0].FILE_NAME, folderName: DOWNLOAD_URL + queryResultJSON.response.docs[0].FILE_PATH, fileName : queryResultJSON.response.docs[0].FILE_NAME, originalName: chunk } );
} else {
console.log("NOT FOUND")
resolve ({fullPath: "N/A" , folderName: "N/A", fileName : "N/A" , originalName : textureName} );
}
}
}
}
xhr.send();
});
}
</script>
</body>
</html>