Search code examples
javascriptpythonflaskhdf5

Read HDF5 from Browser with Javascript version_hint.toFixed is not a function


So i have some HDF5 files from Matlab with .mat as the format (changed to .hdf5 without any difference) in Python with h5py i can extract the data i want without any problems, i run a Flask application so i want to do this front end.

On the site there is a form/fileupload and a button to read the file, when the file is uploaded i want to get the keys from the file and show the keys.

I've tried using jsfive and h5wasm but they both give me the same error on the file that worked on python: Uncaught TypeError: version_hint.toFixed is not a function

The code iv'e tried is this for jsfive:

Import from HTML: <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/browser/hdf5.js"></script>

function signalsSearch() {
    var file_input = document.getElementById('signal-file');
    var file = file_input.files[0];
    let datafilename = file.name;
    let reader = new FileReader();
    reader.addEventListener("loadend", function(evt) {
        let barr = evt.target.result;
        var f = new hdf5.File(barr, datafilename);
        let signals = f.keys();
        console.log(signals);
    });
    reader.readAsArrayBuffer(file);
}

Here it is the var f = new hdf5.File(barr, datafilename); that throws the error

And this for h5wasm:

import * as hdf5 from "https://cdn.jsdelivr.net/npm/h5wasm@latest/dist/esm/hdf5_hl.js";

await hdf5.ready;

async function loadData() {
    var signals = [];
    let file = $("#signal-file")[0].files[0];
    let data_filename = file.name;
    let ab = await file.arrayBuffer();
    // hdf5.FS.writeFile(data_filename, new Uint8Array(ab));
    let f = new hdf5.File(ab, "r");
    // do somthing with f
    signals = f.keys();
    f.close();
    return signals
}

Here it is the let f = new hdf5.File(ab, "r"); That gives an error, in the example it passes data_filename isntead of ab here but that only gives the error TypeError: First argument to DataView constructor must be an ArrayBuffer

So from what i've found the error is probably that toFixed() gets a string value instead of a int or float, what i dont know is why and if it's fixable. Can it be that the way the hdf5 is formatted isn't readable by the two libraries but is on h5py?

In that case what can i do, iv'e tried making a submit button and doing the reading in python and passing the result back to the site, but that makes the site reload and scroll back to the top which is alittle annoying since this is part of a huge form.


Solution

  • I fixed this by making an api that i send the file to and fetch the answer from that is the list from the file processed in python backend. I don't know if this is the correct way to do things like this but atleast it works.

    This is the function in javascript:

    /**
     * Async read a hdf5 file by posting to backend and waiting for the return value containing the signals in a list
     * @param {string} fileInputName Name of the input with the file to read from
     * @param {*} sectionNumber The section of the input to read the file from
     * @returns A list of the signals availible in the Hdf5 file
     */
    async function getSignalsFromHdf5(fileInputName, sectionNumber=1) {
        // Create a new form for sending the file
        let formData =  new FormData();
        // Append the file
        formData.append("file", $('input[name="' + fileInputName + '"]')[sectionNumber - 1].files[0]);
        // Send file and get response
        if ($('input[name="' + fileInputName + '"]')[sectionNumber - 1].files.length > 0) {
            var keys = await fetch('http://urlofmysite:5005/api/get-keys-from-hdf5', {
                method: 'POST',
                body: formData
        }).then((response) => {
                return response.json();
            }).then((myJson) => {
                return myJson['keys'];
            });
        }
        else {
            return []
        }
        return keys
    }
    

    And heres the backend python code:

    # Download HDF5 file, return the keys and delete the file again
    @app.route('/api/get-keys-from-hdf5', methods=['GET', 'POST'])
    def get_keys_from_hdf5():
        if request.method == 'POST':
            file = request.files['file']
            keys = read_hdf5_file_keys(file)
            response = jsonify({"keys": keys})
            response.headers.add('Access-Control-Allow-Origin', '*')
            return response
    

    I never found a way to read them in javascript without modifying the existing libraries or making a new one.