Commit 85b3d359 authored by ba yaye-awa's avatar ba yaye-awa
Browse files

use ThreeJS to view 3D cube

parent 4bcb4c0b
......@@ -27,6 +27,9 @@ import re
from functools import reduce
from matplotlib import pyplot as pp
import yt
from spectral_cube import SpectralCube
def cmap2palette (palette_name):
x = pp.get_cmap(palette_name)
......@@ -997,6 +1000,58 @@ class DataBlock:
result = self.__createFITS0( iRA, iDEC)
self.__logger.debug("createFITS: exiting")
return result
def getYtObj(self, relFITSFilePath, product):
self.__logger.debug("getYtObj: entering")
result = {"status": False, "message": "", "result": None}
if not self.is3D():
result["message"]="This dataset does not have dimesions compatible with the foreseen operation"
else:
try:
absFITSFilePath = DataBlock.getFITSFilePrefix() + relFITSFilePath
absOBJFilePath = DataBlock.getOBJFilePrefix() + product
#create cube by extracting data from the fits
cube= fits.getdata(absFITSFilePath)
cube = cube.squeeze()
cube[np.isnan(cube)] = np.nanmin(cube)
cube.shape
Nsigma = 0.1
#define the delimeter
reduce=0.4 # 20% of the nb of x and y channels (to avoid the edge noise)
schrink = 1 # velocity axis: new v-axis size is RA/DEC-axis size / schrink
chan_min = 86 # 0 #121 # 24
chan_max = 100 # len(cube[:,1,1]) #233 # 86
cube.shape
rms=cube.std()
cube.clip(Nsigma*rms)
subcube = cube[chan_min:chan_max,:,:]
print(subcube.shape)
print(rms)
max_shape=max(subcube.shape)
data = dict(density = subcube)
ytds = yt.load_uniform_grid(data, subcube.shape)
print("Dim")
print(ytds.domain_dimensions)
ytds.periodicity = (True,)*3
dd = ytds.all_data()
region = ytds.r[:,:,:]
surf = ytds.surface(region, "density", Nsigma*rms)
surf.export_obj(absOBJFilePath)
result = {"status": True, "message": "", "result": product}
except Exception as e:
result["message"]="An exception occurred with message {%s}" % e
result["status"]= False
result["result"]=None
self.__logger.debug("getYtObj : exiting")
return result
def RADECRangeInDegrees( self):
self.__logger.debug("RADECRangeInDegrees: entering")
......
......@@ -372,50 +372,15 @@ class DataManagerImpl :
#
#
#
def getYtObj(self):
self.__logger.debug("ytObj : entering")
name = "Abell1795.CO.image.pbcor"
filename = FITSFilePrefix+"Abell1795.CO.image.pbcor.fits"
fileout = OBJFilePrefix+"Abell1795.CO.image.pbcor"
#create cube by extracting data from the fits
cube= fits.getdata(filename)
cube = cube.squeeze()
cube[np.isnan(cube)] = np.nanmin(cube)
cube.shape
Nsigma = 0.1
#define the delimeter
reduce=0.4 # 20% of the nb of x and y channels (to avoid the edge noise)
schrink = 1 # velocity axis: new v-axis size is RA/DEC-axis size / schrink
chan_min = 86 # 0 #121 # 24
chan_max = 100# len(cube[:,1,1]) #233 # 86
cube.shape
rms=cube.std()
maxi=cube.max()
mini=cube.max()
cube.clip(Nsigma*rms)
subcube = cube[chan_min:chan_max,:,:]
print(subcube.shape)
print(maxi)
print(rms)
max_shape=max(subcube.shape)
data = dict(density = subcube)
ytds = yt.load_uniform_grid(data, subcube.shape)
print("Dim")
print(ytds.domain_dimensions)
ytds.periodicity = (True,)*3
dd = ytds.all_data()
region = ytds.r[:,:,:]
surf = ytds.surface(region, "density", Nsigma*rms)
surf.export_obj(fileout)
self.__logger.debug("ytObj : exiting")
return {"status": True, "message": "", "result": name}
def getYtObj(self,relFITSFilePath,product):
self.__logger.debug("getYtObj : entering")
self.__logger.debug("relFITSFilePath = %r, product= %r" % (relFITSFilePath,product))
result = self.__checkPresence(relFITSFilePath)
if result :
result = self.__dataBlocks[relFITSFilePath].getYtObj(relFITSFilePath,product)
self.__logger.debug("getYtObj : exiting")
return result
#
#
# End of the DataManagerImpl class
......
......@@ -1030,8 +1030,9 @@ def getYtObj():
logger.debug("getYtObj - wrapper : entering")
try:
#body = byteify(json.loads(request.body.read()))
result = dm.getYtObj()
body = byteify(json.loads(request.body.read()))
relFITSFilePath = rebuildFilename(body['relFITSFilePath'])
result = dm.getYtObj(relFITSFilePath, body['product'])
except Exception as e:
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback.print_exc()
......
......@@ -12,7 +12,6 @@ var connectArtemix = require('./routes/connectArtemix')
var fitsBrowser = require('./routes/fitsBrowser');
var monitor = require('./routes/monitor');
var purge = require('./routes/purge');
var ytObj = require('./routes/ytObj');
var app = express();
var yafits_samp = process.env.YAFITS_SAMPDIR;
......@@ -48,7 +47,6 @@ app.use('/', olqv);
app.use('/monitor', monitor);
app.use('/purge', purge);
app.use('/', fitsBrowser);
app.use('/ytObj', ytObj);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -6,12 +6,15 @@ const path = require("path");
const uuidv1 = require('uuid/v1');
const request = require('request');
const url = require('url');
const obj2gltf = require('obj2gltf');
var ENTER = function () { console.log(arguments.callee.name + ": entering."); };
var EXIT = function () { console.log(arguments.callee.name + ": exiting."); };
var PNG_ROOT_DIR = '/home/partemix/dataroot/PNG';
var OBJ_ROOT_DIR = '/home/partemix/dataroot/OBJ';
var SAMP_DIR = '/home/partemix/dataroot/SAMP';
var yafitssHost = process.env.YAFITSS_HOST;
......@@ -158,6 +161,15 @@ var clienthttp = {
callback(error, response, body);
});
},
getYtObj : function(relFITSFilePath, callback) {
// retrieve the product name, i.e. the simple filename without extension nor prefix.
var product = path.parse(relFITSFilePath).name;
let input = {"relFITSFilePath": relFITSFilePath, "product":product};
request.post(this.server+"/getYtObj", {json: true,body:input}, function(error, response, body){
callback(error, response, body);
});
},
renderingCapabilities: function(callback) {
request(this.server+"/renderingCapabilities", {json: true}, function (error, response, body){
......@@ -721,22 +733,29 @@ router.post('/getContours', function(req, res, next) {
console.log("router.post('/getContours', function(req, res, next) {: exiting");
});
/*router.post('/ytObj', function(req, res, next) {
console.log("router.post('/ytObj', function(req, res, next) { : entering");
clienthttp.getYtObj(req.body.relFITSFilePath, (error, response, body)=>{
console.log("getYtObj callback : entering");
router.get("/getYtObj", function(req, res, next) {
console.log('router.get("/", function(req, res, next) { : entering '+ req.query.relFITSFilePath );
clienthttp.getYtObj(req.query.relFITSFilePath,(error, response, body) => {
console.log("getYtObj callback : entering");
if (error) {
console.log(error);
}
else {
res.send(body);
console.log("body result "+body["result"]);
var gltfFile = OBJ_ROOT_DIR+"/"+body["result"]+".gltf";
//create gltfFile
obj2gltf(OBJ_ROOT_DIR+"/"+body["result"]+".obj").then(function(gltf) {
const data = Buffer.from(JSON.stringify(gltf));
fs.writeFileSync(gltfFile, data);
}).then(function(){
console.log(gltfFile);
res.render("getYtObj",{gltfFile:URLRoot(req.headers.referer)+"/"+body["result"]+".gltf"});
});
}
console.log("getYtObj callback : exiting");
console.log("getYtObj callback : exiting");
});
console.log("router.post('/ytObj', function(req, res, next) { : exiting");
}); */
});
module.exports = router;
var express = require('express');
var router = express.Router();
const request = require('request');
const obj2gltf = require('obj2gltf');
const fs = require('fs');
var FITS_ROOT_DIR = '/home/partemix/dataroot/FITS';
var OBJ_ROOT_DIR = '/home/partemix/dataroot/OBJ';
var yafitssHost = process.env.YAFITSS_HOST;
var yafitssPort = process.env.YAFITSS_PORT;
console.log("I'll collaborate with ..." + yafitssHost + ":" + yafitssPort + " ...for the FITS files services");
var clienthttp = {
server : "http://"+yafitssHost+":"+yafitssPort+"/artemix",
getYtObj : function(callback) {
request.post(this.server+"/getYtObj", {json: true}, function(error, response, body){
callback(error, response, body);
});
}
};
router.get("/", function(req, res, next) {
console.log('ytObj router.get("/", function(req, res, next) { : entering' );
//var relFITSFilePath = FITS_ROOT_DIR + '/2013.1.00073.S/science_goal.uid___A001_X12f_X20b/group.uid___A001_X12f_X20c/member.uid___A001_X12f_X20d/product/M87_CO_v_0_2_1_image.image.fits'
clienthttp.getYtObj((error, response, body) => {
console.log("ytObj callback : entering");
console.log("body result "+body["result"]);
obj2gltf(OBJ_ROOT_DIR+"/"+body["result"]+".obj").then(function(gltf) {
const data = Buffer.from(JSON.stringify(gltf));
fs.writeFileSync(OBJ_ROOT_DIR+"/"+body["result"]+".gltf", data);
});
/* if (error ){
var message = error.toString();
res.setHeader('Content-type', 'application/json');
res.send(JSON.stringify({"status":false, "message": message}));
}
else if (response["statusCode"] == 500) {
res.send(JSON.stringify({status: false, message: response["body"]}));
}
else if (response["body"]["status"] == false) {
res.render("error", {message: response["body"]["message"], error : {"status" : "", "stack" : ""}});
}
else {
let x = JSON.parse(response["body"])
console.log(JSON.parse(response["body"]));
res.redirect("/monitor");
}*/
console.log("ytObj callback : exiting");
});
});
module.exports = router;
<!DOCTYPE html>
<html>
<head>
<title>ThreeJS cube viewer</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="../javascript/three.min.js"></script>
<script src="../javascript/GLTFLoader.js"></script>
<script src="../javascript/OrbitControls.js"></script>
<script>
// Load 3D Scene
var scene = new THREE.Scene();
// Load Camera Perspektive
var camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.set( 1, 1, 20 );
// Load a Renderer
var renderer = new THREE.WebGLRenderer({ alpha: false });
renderer.setClearColor( 0xC5C5C3 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Load the Orbitcontroller
var controls = new THREE.OrbitControls( camera, renderer.domElement );
// Load Light
var ambientLight = new THREE.AmbientLight( 0xcccccc );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 0, 1, 1 ).normalize();
scene.add( directionalLight );
// glTf Loader
var loader = new THREE.GLTFLoader();
loader.load( '<%=gltfFile%>', function ( gltf ) {
var object = gltf.scene;
gltf.scene.scale.set( 2, 2, 2 );
gltf.scene.position.x = 0; //Position (x = right+ left-)
gltf.scene.position.y = 0; //Position (y = up+, down-)
gltf.scene.position.z = 0; //Position (z = front +, back-)
scene.add( gltf.scene );
});
function animate() {
render();
requestAnimationFrame( animate );
}
function render() {
renderer.render( scene, camera );
}
render();
animate();
</script>
</body>
</html>
......@@ -203,6 +203,7 @@
</button>
<img src="../samphub.png" style="width:30px; height:30px" data-toggle="collapse" data-target="#sampRegistry" aria-controls="sampRegistry" aria-expanded="false" aria-label="Toggle navigation"/>
<!--<div><a id="jupyter" href="#" target="_blank"><img src="../jupyter.png" style="width:30px; height:30px" title="jupyter"/></a></div>-->
<div><a id="threejs" href="#" target="_blank">Cube viewer</a></div>
<div><a href="http://artemix.obspm.fr/fits/browse" target="_blank">See more FITS files...</a></div>
<div id="cubeInfos" style="font-size:15px; color: white"></div>
</nav>
......@@ -2335,6 +2336,7 @@ var SAMPPNGPublishControl = (function (Control) {
<%}%>
$( document ).ready(function() {
console.log("$( document ).ready(function() {: entering");
$("a#threejs").attr("href", "<%=urlRoot%>/getYtObj?relFITSFilePath="+relFITSFilePath);
//$("a#jupyter").attr("href", "https://romeo.obspm.fr:8500/user/partemix/notebooks/openURL.ipynb?kernel_name=python3&?Variable1="+relFITSFilePath+"&?kernel_name=python3");
/*
** Set up everything required to fill and display the FITS header.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment