Skip to content

Instantly share code, notes, and snippets.

@oeway
Last active March 29, 2021 14:12
Show Gist options
  • Save oeway/0f19fe2508656bc56a24909e5f9bfc46 to your computer and use it in GitHub Desktop.
Save oeway/0f19fe2508656bc56a24909e5f9bfc46 to your computer and use it in GitHub Desktop.
Python script for uploading files to figshare
#!/usr/bin/env python
'''
Uploading files to figshare
https://docs.figshare.com/#upload_files_example_upload_on_figshare
'''
import hashlib
import json
import os
import requests
from requests.exceptions import HTTPError
BASE_URL = 'https://api.figshare.com/v2/{endpoint}'
TOKEN = '' # paste your personal token here
CHUNK_SIZE = 1048576
TITLE = 'My Data'
FILE_PATH = '/path/to/my/file'
def raw_issue_request(method, url, data=None, binary=False):
headers = {'Authorization': 'token ' + TOKEN }
if data is not None and not binary:
data = json.dumps(data)
response = requests.request(method, url, headers=headers, data=data)
try:
response.raise_for_status()
try:
data = json.loads(response.content)
except ValueError:
data = response.content
except HTTPError as error:
print('Caught an HTTPError: {}'.format(error))
print('Body:\n', response.content)
raise
return data
def issue_request(method, endpoint, *args, **kwargs):
return raw_issue_request(method, BASE_URL.format(endpoint=endpoint), *args, **kwargs)
def list_articles():
result = issue_request('GET', 'account/articles')
print('Listing current articles:')
if result:
for item in result:
print(u'{}'.format(item))
else:
print(' No articles.')
print()
def create_article(title):
data = {
'title': title # You may add any other information about the article here as you wish.
}
result = issue_request('POST', 'account/articles', data=data)
print('Created article:', result['location'], '\n')
result = raw_issue_request('GET', result['location'])
return result['id']
def list_files_of_article(article_id):
result = issue_request('GET', 'account/articles/{}/files'.format(article_id))
print('Listing files for article {}:'.format(article_id))
if result:
for item in result:
print(' {id} - {name}'.format(**item))
else:
print(' No files.')
print()
def get_file_check_data(file_name):
with open(file_name, 'rb') as fin:
md5 = hashlib.md5()
size = 0
data = fin.read(CHUNK_SIZE)
while data:
size += len(data)
md5.update(data)
data = fin.read(CHUNK_SIZE)
return md5.hexdigest(), size
def initiate_new_upload(article_id, file_name):
endpoint = 'account/articles/{}/files'
endpoint = endpoint.format(article_id)
md5, size = get_file_check_data(file_name)
data = {'name': os.path.basename(file_name),
'md5': md5,
'size': size}
result = issue_request('POST', endpoint, data=data)
print('Initiated file upload:', result['location'], '\n')
result = raw_issue_request('GET', result['location'])
return result
def complete_upload(article_id, file_id):
issue_request('POST', 'account/articles/{}/files/{}'.format(article_id, file_id))
def upload_parts(file_info, file_path):
url = '{upload_url}'.format(**file_info)
result = raw_issue_request('GET', url)
print('Uploading parts:')
with open(file_path, 'rb') as fin:
for part in result['parts']:
upload_part(file_info, fin, part)
print()
def upload_part(file_info, stream, part):
udata = file_info.copy()
udata.update(part)
url = '{upload_url}/{partNo}'.format(**udata)
stream.seek(part['startOffset'])
data = stream.read(part['endOffset'] - part['startOffset'] + 1)
raw_issue_request('PUT', url, data=data, binary=True)
print(' Uploaded part {partNo} from {startOffset} to {endOffset}'.format(**part))
def main():
# We first create the article
list_articles()
article_id = create_article(TITLE)
# article_id = '14308046'
list_articles()
list_files_of_article(article_id)
# Then we upload the file.
file_info = initiate_new_upload(article_id, FILE_PATH)
# Until here we used the figshare API; following lines use the figshare upload service API.
upload_parts(file_info, FILE_PATH)
# We return to the figshare API to complete the file upload process.
complete_upload(article_id, file_info['id'])
list_files_of_article(article_id)
if __name__ == '__main__':
main()
<docs>
[TODO: write documentation for this plugin.]
</docs>
<config lang="json">
{
"name": "VizarrFigshare",
"type": "web-worker",
"tags": [],
"ui": "",
"version": "0.1.0",
"cover": "",
"description": "Reading Vizarr using reference store",
"icon": "extension",
"inputs": null,
"outputs": null,
"api_version": "0.1.8",
"env": "",
"permissions": [],
"requirements": ["https://unpkg.com/zarr@0.4.0/zarr.umd.js"],
"dependencies": []
}
</config>
<script lang="javascript">
// Using the FileReferenceStore made by Trevor Manz
// https://observablehq.com/d/a417a770860fbb64
class FileReferenceStore {
constructor(ref, target) {
this.ref = ref;
this.target = target;
}
_url(urlPath) {
if(!urlPath){
return this.target
}
const [protocol, path] = urlPath.split('://');
if (protocol === 'https' || protocol === 'http') {
return urlPath;
}
if (protocol === 'gc') {
return 'https://storage.googleapis.com/' + path;
}
throw Error("Protocol not supported, got: " + JSON.stringify(protocol));
}
async getItem(key) {
const res = this.ref[key];
if (!res) {
// Key not in store
throw new zarr.KeyError(key);
}
if (res?.length !== 3) {
// JSON data entry in reference
const meta = typeof res === 'string' ? res : JSON.stringify(res)
const enc = new TextEncoder().encode(meta);
return enc.buffer;
}
const [urlPath, offset, size] = res;
const url = this._url(urlPath);
const headers = {
Range: `bytes=${offset}-${offset + size - 1}`
};
const value = await fetch(url, { headers}).then(res => res.arrayBuffer());
return value;
}
containsItem(key) {
return key in this.ref;
}
static async fromUrl(url, targetUrl) {
const ref = await fetch(url).then(res => res.json());
return new FileReferenceStore(ref, targetUrl);
}
}
class ImJoyPlugin {
async setup() {
api.log('initialized')
}
async run(ctx) {
const refUrl = 'https://ndownloader.figshare.com/files/27246875?private_link=5a9d8e9e59dab21e4b85'
const targetUrl = 'https://ndownloader.figshare.com/files/27246878?private_link=5a9d8e9e59dab21e4b85'
const store = await FileReferenceStore.fromUrl(refUrl, targetUrl);
const viewer = await api.createWindow({src: 'https://hms-dbmi.github.io/vizarr'})
const img = {
"source": store,
"name": "Image",
"channel_axis": 1,
"colors": ["#0000FF", "#FF0000", "#00FFFF", "#00FF00"], // optional
"names": ["DAPI", "red", "cyan", "green"], // optional, default channel_X
"visibilities": [true, true, true, true], // optional, default True
"contrast_limits": [[60, 500], [70, 300], [70, 5000], [70, 1500]], // optional, but recommended
}
viewer.add_image(img)
}
}
api.export(new ImJoyPlugin())
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment