diff --git a/client/app.js b/client/app.js index e809e61721..c4db96216a 100644 --- a/client/app.js +++ b/client/app.js @@ -193,6 +193,25 @@ let newWorkflow = (parent, mdlPath, isSpatial, type) => { }); } +tooltipSetup = () => { + $(function () { + $('[data-toggle="tooltip"]').tooltip(); + $('[data-toggle="tooltip"]').on('click ', function () { + $('[data-toggle="tooltip"]').tooltip("hide"); + }); + }); +} + +documentSetup = () => { + tooltipSetup(); + $(document).on('shown.bs.modal', function (e) { + $('[autofocus]', e.target).focus(); + }); + $(document).on('hide.bs.modal', '.modal', function (e) { + e.target.remove(); + }); +} + module.exports = { routePrefix: routePrefix, getApiPath: getApiPath, @@ -202,7 +221,9 @@ module.exports = { changeCollapseButtonText: changeCollapseButtonText, newWorkflow: newWorkflow, getXHR: getXHR, - postXHR: postXHR + postXHR: postXHR, + tooltipSetup: tooltipSetup, + documentSetup: documentSetup }; diff --git a/client/modals.js b/client/modals.js index 93a5e044d9..b9ccd2ff77 100644 --- a/client/modals.js +++ b/client/modals.js @@ -223,6 +223,40 @@ let templates = { ` + }, + presentationLinks : (modalID, title, name, headers, links) => { + return ` + ` } } @@ -541,5 +575,10 @@ module.exports = { ` + }, + presentationLinks : (title, name, headers, links) => { + let modalID = "presentationLinksModal" + + return templates.presentationLinks(modalID, title, name, headers, links); } } \ No newline at end of file diff --git a/client/model-view/model-view.js b/client/model-view/model-view.js new file mode 100644 index 0000000000..ab7d5a0129 --- /dev/null +++ b/client/model-view/model-view.js @@ -0,0 +1,378 @@ +/* +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +let $ = require('jquery'); +let path = require('path'); +let _ = require('underscore'); +//support files +let app = require('../app'); +let modals = require('../modals'); +let tests = require('../views/tests'); +//models +let Domain = require('../models/domain'); +//views +let View = require('ampersand-view'); +let InputView = require('../views/input'); +let RulesView = require('./views/rules-view'); +let EventsView = require('./views/events-view'); +let SpeciesView = require('./views/species-view'); +let DomainViewer = require('./views/domain-viewer'); +let ReactionsView = require('./views/reactions-view'); +let ParametersView = require('./views/parameters-view'); +let SBMLComponentsView = require('./views/sbml-components-view'); +let InitialConditionsView = require('./views/initial-conditions-view'); +let BoundaryConditionsView = require('./views/boundary-conditions-view'); +//templates +let template = require('./modelView.pug'); + +module.exports = View.extend({ + template: template, + events: { + 'change [data-hook=all-continuous]' : 'setDefaultMode', + 'change [data-hook=all-discrete]' : 'setDefaultMode', + 'change [data-hook=advanced]' : 'setDefaultMode', + 'change [data-hook=edit-volume]' : 'updateVolumeViewer', + 'click [data-hook=collapse-mv-advanced-section]' : 'changeCollapseButtonText' + }, + initialize: function(attrs, options) { + View.prototype.initialize.apply(this, arguments); + this.readOnly = attrs.readOnly ? attrs.readOnly : false; + let modeMap = {continuous: "Concentration", discrete: "Population", dynamic: "Hybrid Concentration/Population"}; + this.modelMode = modeMap[this.model.defaultMode]; + }, + render: function(attrs, options) { + View.prototype.render.apply(this, arguments); + this.updateSpeciesInUse(); + this.updateParametersInUse(); + this.renderDomainViewer(); + this.renderSpeciesView(); + this.renderInitialConditionsView(); + this.renderParametersView(); + this.renderReactionsView(); + this.renderEventsView(); + this.renderRulesView(); + this.renderBoundaryConditionsView(); + this.renderSbmlComponentView(); + this.renderSystemVolumeView(); + if(this.readOnly) { + this.setReadOnlyMode("model-mode"); + this.setReadOnlyMode("system-volume") + }else { + if(this.model.defaultMode === "" && !this.model.is_spatial){ + this.getInitialDefaultMode(); + }else { + let dataHooks = {'continuous':'all-continuous', 'discrete':'all-discrete', 'dynamic':'advanced'}; + $(this.queryByHook(dataHooks[this.model.defaultMode])).prop('checked', true); + if(this.model.is_spatial) { + $(this.queryByHook("advanced-model-mode")).css("display", "none"); + $(this.queryByHook("system-volume-container")).css("display", "none"); + } + } + this.model.reactions.on("change", function (reactions) { + this.updateSpeciesInUse(); + this.updateParametersInUse(); + }, this); + this.model.eventsCollection.on("add change remove", function (){ + this.updateSpeciesInUse(); + this.updateParametersInUse(); + }, this); + this.model.rules.on("add change remove", function() { + this.updateSpeciesInUse(); + this.updateParametersInUse(); + }, this); + } + }, + changeCollapseButtonText: function (e) { + app.changeCollapseButtonText(this, e); + }, + getInitialDefaultMode: function () { + let self = this; + if(document.querySelector('#defaultModeModal')) { + document.querySelector('#defaultModeModal').remove(); + } + let modal = $(modals.renderDefaultModeModalHtml()).modal(); + let continuous = document.querySelector('#defaultModeModal .concentration-btn'); + let discrete = document.querySelector('#defaultModeModal .population-btn'); + let dynamic = document.querySelector('#defaultModeModal .hybrid-btn'); + continuous.addEventListener('click', function (e) { + self.setInitialDefaultMode(modal, "continuous"); + }); + discrete.addEventListener('click', function (e) { + self.setInitialDefaultMode(modal, "discrete"); + }); + dynamic.addEventListener('click', function (e) { + self.setInitialDefaultMode(modal, "dynamic"); + }); + }, + renderBoundaryConditionsView: function () { + if(!this.model.is_spatial) { return } + if(this.boundaryConditionsView) { + this.boundaryConditionsView.remove(); + } + this.boundaryConditionsView = new BoundaryConditionsView({ + collection: this.model.boundaryConditions, + readOnly: this.readOnly + }); + let hook = "boundary-conditions-view-container"; + app.registerRenderSubview(this, this.boundaryConditionsView, hook); + }, + renderDomainViewer: function(domainPath=null) { + if(!this.model.is_spatial) { return } + if(this.domainViewer) { + this.domainViewer.remove(); + } + if(domainPath && domainPath !== "viewing") { + let self = this; + let queryStr = "?path=" + this.model.directory + "&domain_path=" + domainPath; + let endpoint = path.join(app.getApiPath(), "spatial-model/load-domain") + queryStr; + app.getXHR(endpoint, { + always: function (err, response, body) { + let domain = new Domain(body.domain); + self.domainViewer = new DomainViewer({ + parent: self, + model: domain, + domainPath: domainPath, + readOnly: self.readOnly + }); + app.registerRenderSubview(self, self.domainViewer, 'domain-viewer-container'); + } + }); + }else{ + this.domainViewer = new DomainViewer({ + parent: this, + model: this.model.domain, + domainPath: domainPath, + readOnly: this.readOnly + }); + app.registerRenderSubview(this, this.domainViewer, 'domain-viewer-container'); + } + }, + renderEventsView: function () { + if(this.model.is_spatial) { return } + if(this.eventsView) { + this.eventsView.remove(); + } + this.eventsView = new EventsView({ + collection: this.model.eventsCollection, + readOnly: this.readOnly + }); + let hook = "events-view-container"; + app.registerRenderSubview(this, this.eventsView, hook); + }, + renderInitialConditionsView: function () { + if(!this.model.is_spatial) { return } + if(this.initialConditionsView) { + this.initialConditionsView.remove(); + } + this.initialConditionsView = new InitialConditionsView({ + collection: this.model.initialConditions, + readOnly: this.readOnly + }); + let hook = "initial-conditions-view-container"; + app.registerRenderSubview(this, this.initialConditionsView, hook); + }, + renderParametersView: function () { + if(this.parametersView) { + this.parametersView.remove(); + } + this.parametersView = new ParametersView({ + collection: this.model.parameters, + readOnly: this.readOnly + }); + let hook = "parameters-view-container"; + app.registerRenderSubview(this, this.parametersView, hook); + }, + renderReactionsView: function () { + if(this.reactionsView) { + this.reactionsView.remove(); + } + this.reactionsView = new ReactionsView({ + collection: this.model.reactions, + readOnly: this.readOnly + }); + let hook = "reactions-view-container"; + app.registerRenderSubview(this, this.reactionsView, hook); + }, + renderRulesView: function () { + if(this.model.is_spatial) { return } + if(this.rulesView) { + this.rulesView.remove(); + } + this.rulesView = new RulesView({ + collection: this.model.rules, + readOnly: this.readOnly + }); + let hook = "rules-view-container"; + app.registerRenderSubview(this, this.rulesView, hook); + }, + renderSbmlComponentView: function () { + if(this.model.is_spatial || !this.model.functionDefinitions.length) { return } + if(this.sbmlComponentView) { + this.sbmlComponentView.remove(); + } + this.sbmlComponentView = new SBMLComponentsView({ + functionDefinitions: this.model.functionDefinitions, + readOnly: this.readOnly + }); + let hook = "sbml-components-view-container"; + app.registerRenderSubview(this, this.sbmlComponentView, hook); + }, + renderSpeciesView: function () { + if(this.speciesView) { + this.speciesView.remove(); + } + this.speciesView = new SpeciesView({ + collection: this.model.species, + spatial: this.model.is_spatial, + defaultMode: this.model.defaultMode, + readOnly: this.readOnly + }); + let hook = "species-view-container"; + app.registerRenderSubview(this, this.speciesView, hook); + }, + renderSystemVolumeView: function () { + if(this.systemVolumeView) { + this.systemVolumeView.remove(); + } + this.systemVolumeView = new InputView ({ + parent: this, + required: true, + name: 'system-volume', + label: 'Volume: ', + tests: tests.valueTests, + modelKey: 'volume', + valueType: 'number', + value: this.model.volume, + }); + app.registerRenderSubview(this, this.systemVolumeView, 'edit-volume'); + if(this.model.defaultMode === "continuous") { + $(this.queryByHook("system-volume-container")).collapse("hide") + } + $(this.queryByHook("view-volume")).html("Volume: " + this.model.volume) + }, + setAllSpeciesModes: function (prevMode) { + let self = this; + this.model.species.forEach(function (specie) { + specie.mode = self.model.defaultMode; + self.model.species.trigger('update-species', specie.compID, specie, false, true); + }); + let switchToDynamic = (!Boolean(prevMode) || prevMode !== "dynamic") && this.model.defaultMode === "dynamic"; + let switchFromDynamic = Boolean(prevMode) && prevMode === "dynamic" && this.model.defaultMode !== "dynamic"; + if(switchToDynamic || switchFromDynamic) { + this.speciesView.renderEditSpeciesView(); + this.speciesView.renderViewSpeciesView(); + } + }, + setDefaultMode: function (e) { + let prevMode = this.model.defaultMode; + this.model.defaultMode = e.target.dataset.name; + this.speciesView.defaultMode = e.target.dataset.name; + this.setAllSpeciesModes(prevMode); + this.toggleVolumeContainer(); + }, + setInitialDefaultMode: function (modal, mode) { + var dataHooks = {'continuous':'all-continuous', 'discrete':'all-discrete', 'dynamic':'advanced'}; + modal.modal('hide'); + $(this.queryByHook(dataHooks[mode])).prop('checked', true); + this.model.defaultMode = mode; + this.speciesView.defaultMode = mode; + this.setAllSpeciesModes(); + this.toggleVolumeContainer(); + }, + setReadOnlyMode: function (component) { + $(this.queryByHook(component + '-edit-tab')).addClass("disabled"); + $(".nav .disabled>a").on("click", function(e) { + e.preventDefault(); + return false; + }); + $(this.queryByHook(component + '-view-tab')).tab('show'); + $(this.queryByHook('edit-' + component)).removeClass('active'); + $(this.queryByHook('view-' + component)).addClass('active'); + }, + toggleVolumeContainer: function () { + if(!this.model.is_spatial) { + if(this.model.defaultMode === "continuous") { + $(this.queryByHook("system-volume-container")).collapse("hide"); + }else{ + $(this.queryByHook("system-volume-container")).collapse("show"); + } + } + }, + update: function () {}, + updateParametersInUse: function () { + var parameters = this.model.parameters; + var reactions = this.model.reactions; + var events = this.model.eventsCollection; + var rules = this.model.rules; + parameters.forEach(function (param) { param.inUse = false; }); + var updateInUse = function (param) { + _.where(parameters.models, { compID: param.compID }) + .forEach(function (param) { + param.inUse = true; + }); + } + reactions.forEach(function (reaction) { + if(reaction.reactionType !== "custom-propensity"){ + updateInUse(reaction.rate); + } + }); + events.forEach(function (event) { + event.eventAssignments.forEach(function (assignment) { + updateInUse(assignment.variable) + }); + }); + rules.forEach(function (rule) { + updateInUse(rule.variable); + }); + }, + updateSpeciesInUse: function () { + var species = this.model.species; + var reactions = this.model.reactions; + var events = this.model.eventsCollection; + var rules = this.model.rules; + species.forEach(function (specie) { specie.inUse = false; }); + var updateInUseForReaction = function (stoichSpecie) { + _.where(species.models, { compID: stoichSpecie.specie.compID }) + .forEach(function (specie) { + specie.inUse = true; + }); + } + var updateInUseForOther = function (specie) { + _.where(species.models, { compID: specie.compID }) + .forEach(function (specie) { + specie.inUse = true; + }); + } + reactions.forEach(function (reaction) { + reaction.products.forEach(updateInUseForReaction); + reaction.reactants.forEach(updateInUseForReaction); + }); + events.forEach(function (event) { + event.eventAssignments.forEach(function (assignment) { + updateInUseForOther(assignment.variable) + }); + }); + rules.forEach(function (rule) { + updateInUseForOther(rule.variable); + }); + }, + updateValid: function () {}, + updateVolumeViewer: function (e) { + $(this.queryByHook("view-volume")).html("Volume: " + this.model.volume); + } +}); \ No newline at end of file diff --git a/client/model-view/modelView.pug b/client/model-view/modelView.pug new file mode 100644 index 0000000000..405185cd64 --- /dev/null +++ b/client/model-view/modelView.pug @@ -0,0 +1,119 @@ +div#model-view + + div.card + + div.card-header.pb-0 + + h3.inline.mr-3 Model Mode + + div.inline.mr-3 + + ul.nav.nav-tabs.card-header-tabs(id="model-mode-tabs") + + li.nav-item + + a.nav-link.tab.active(data-hook="model-mode-edit-tab" data-toggle="tab" href="#edit-model-mode") Edit + + li.nav-item + + a.nav-link.tab(data-hook="model-mode-view-tab" data-toggle="tab" href="#view-model-mode") View + + div.card-body + + p.mb-0 + | Concentration - Variables will only be represented using continuous (floating point) values.
+ | Population - Variables will only be represented using discrete (integer count) values.
+ if !this.model.is_spatial + | Hybrid Concentration/Population - Allows a variables to be represented using continuous and/or discrete values. + + div.tab-content(id="model-mode-section" data-hook="model-mode-section") + + div.tab-pane.active(id="edit-model-mode" data-hook="edit-model-mode") + + hr + + div.row + div.col-sm-4 + input.mr-2(type="radio" name="default-mode" data-hook="all-continuous" data-name="continuous") + span Concentration + div.col-sm-4 + input.mr-2(type="radio" name="default-mode" data-hook="all-discrete" data-name="discrete") + span Population + div.col-sm-4(data-hook="advanced-model-mode") + input.mr-2(type="radio" name="default-mode" data-hook="advanced" data-name="dynamic") + span Hybrid Concentration/Population + + div.tab-pane(id="view-model-mode" data-hook="view-model-mode") + + hr + + div="Model Mode: " + this.modelMode + + div(data-hook="domain-viewer-container") + + div(data-hook="species-view-container") + + div(data-hook="initial-conditions-view-container") + + div(data-hook="parameters-view-container") + + div(data-hook="reactions-view-container") + + div.card(data-hook="model-view-advanced-container") + + div.card-header.pb-0 + + h3.inline Advanced + + button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#mv-advanced-section" data-hook="collapse-mv-advanced-section") + + + div.collapse(id="mv-advanced-section" data-hook="mv-advanced-section") + + div.card-body + + div(data-hook="events-view-container") + + div(data-hook="rules-view-container") + + div(data-hook="boundary-conditions-view-container") + + div(data-hook="sbml-components-view-container") + + div.card.collapse.show(data-hook="system-volume-container") + + div.card-header.pb-0 + + h3.inline.mr-3 System Volume + + div.inline.mr-3 + + ul.nav.nav-tabs.card-header-tabs(id="volume-tabs") + + li.nav-item + + a.nav-link.tab.active(data-hook="system-volume-edit-tab" data-toggle="tab" href="#edit-system-volume") Edit + + li.nav-item + + a.nav-link.tab(data-hook="system-volume-view-tab" data-toggle="tab" href="#view-system-volume") View + + button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-system-volume", data-hook="collapse-system-volume") + + + div.card-body + + p.mb-0 + | System volume affects custom propensities or stochastic reactions with two reactants. The volume sets the implicit parameter 'vol' which can be used in custom propensity functions. A single well-mixed volume is assumed. Compartments are not currently supported. In most cases this should not be changed. please review your model requirements carefully before changing this property. + + div.collapse.tab-content(id="collapse-system-volume" data-hook="system-volume-section") + + div.tab-pane.active(id="edit-system-volume" data-hook="edit-system-volume") + + hr + + div(data-hook="edit-volume") + + div.tab-pane(id="view-system-volume" data-hook="view-system-volume") + + hr + + div(data-hook="view-volume") diff --git a/client/templates/includes/boundaryConditionsEditor.pug b/client/model-view/templates/boundaryConditionsView.pug similarity index 100% rename from client/templates/includes/boundaryConditionsEditor.pug rename to client/model-view/templates/boundaryConditionsView.pug diff --git a/client/templates/includes/domainViewer.pug b/client/model-view/templates/domainViewer.pug similarity index 100% rename from client/templates/includes/domainViewer.pug rename to client/model-view/templates/domainViewer.pug diff --git a/client/templates/includes/editBoundaryCondition.pug b/client/model-view/templates/editBoundaryCondition.pug similarity index 100% rename from client/templates/includes/editBoundaryCondition.pug rename to client/model-view/templates/editBoundaryCondition.pug diff --git a/client/templates/includes/editCustomStoichSpecie.pug b/client/model-view/templates/editCustomStoichSpecie.pug similarity index 100% rename from client/templates/includes/editCustomStoichSpecie.pug rename to client/model-view/templates/editCustomStoichSpecie.pug diff --git a/client/templates/includes/editEventAssignment.pug b/client/model-view/templates/editEventAssignment.pug similarity index 100% rename from client/templates/includes/editEventAssignment.pug rename to client/model-view/templates/editEventAssignment.pug diff --git a/client/templates/includes/editFunctionDefinition.pug b/client/model-view/templates/editFunctionDefinition.pug similarity index 100% rename from client/templates/includes/editFunctionDefinition.pug rename to client/model-view/templates/editFunctionDefinition.pug diff --git a/client/templates/includes/editInitialCondition.pug b/client/model-view/templates/editInitialCondition.pug similarity index 100% rename from client/templates/includes/editInitialCondition.pug rename to client/model-view/templates/editInitialCondition.pug diff --git a/client/templates/includes/editParameter.pug b/client/model-view/templates/editParameter.pug similarity index 100% rename from client/templates/includes/editParameter.pug rename to client/model-view/templates/editParameter.pug diff --git a/client/templates/includes/editRule.pug b/client/model-view/templates/editRule.pug similarity index 100% rename from client/templates/includes/editRule.pug rename to client/model-view/templates/editRule.pug diff --git a/client/templates/includes/editSpatialSpecies.pug b/client/model-view/templates/editSpatialSpecie.pug similarity index 100% rename from client/templates/includes/editSpatialSpecies.pug rename to client/model-view/templates/editSpatialSpecie.pug diff --git a/client/templates/includes/editSpecies.pug b/client/model-view/templates/editSpecie.pug similarity index 100% rename from client/templates/includes/editSpecies.pug rename to client/model-view/templates/editSpecie.pug diff --git a/client/templates/includes/editStoichSpecie.pug b/client/model-view/templates/editStoichSpecie.pug similarity index 100% rename from client/templates/includes/editStoichSpecie.pug rename to client/model-view/templates/editStoichSpecie.pug diff --git a/client/templates/includes/eventAssignmentsEditor.pug b/client/model-view/templates/eventAssignmentsView.pug similarity index 100% rename from client/templates/includes/eventAssignmentsEditor.pug rename to client/model-view/templates/eventAssignmentsView.pug diff --git a/client/templates/includes/eventDetails.pug b/client/model-view/templates/eventDetails.pug similarity index 100% rename from client/templates/includes/eventDetails.pug rename to client/model-view/templates/eventDetails.pug diff --git a/client/templates/includes/eventListings.pug b/client/model-view/templates/eventListing.pug similarity index 100% rename from client/templates/includes/eventListings.pug rename to client/model-view/templates/eventListing.pug diff --git a/client/templates/includes/eventsEditor.pug b/client/model-view/templates/eventsView.pug similarity index 100% rename from client/templates/includes/eventsEditor.pug rename to client/model-view/templates/eventsView.pug diff --git a/client/templates/includes/initialConditionsEditor.pug b/client/model-view/templates/initialConditionsView.pug similarity index 100% rename from client/templates/includes/initialConditionsEditor.pug rename to client/model-view/templates/initialConditionsView.pug diff --git a/client/templates/includes/parametersEditor.pug b/client/model-view/templates/parametersView.pug similarity index 100% rename from client/templates/includes/parametersEditor.pug rename to client/model-view/templates/parametersView.pug diff --git a/client/templates/includes/reactantProduct.pug b/client/model-view/templates/reactantProduct.pug similarity index 100% rename from client/templates/includes/reactantProduct.pug rename to client/model-view/templates/reactantProduct.pug diff --git a/client/templates/includes/reactionDetails.pug b/client/model-view/templates/reactionDetails.pug similarity index 100% rename from client/templates/includes/reactionDetails.pug rename to client/model-view/templates/reactionDetails.pug diff --git a/client/templates/includes/reactionListing.pug b/client/model-view/templates/reactionListing.pug similarity index 100% rename from client/templates/includes/reactionListing.pug rename to client/model-view/templates/reactionListing.pug diff --git a/client/templates/includes/reactionTypeTemplate.pug b/client/model-view/templates/reactionTypeTemplate.pug similarity index 100% rename from client/templates/includes/reactionTypeTemplate.pug rename to client/model-view/templates/reactionTypeTemplate.pug diff --git a/client/templates/includes/reactionTypes.pug b/client/model-view/templates/reactionTypes.pug similarity index 100% rename from client/templates/includes/reactionTypes.pug rename to client/model-view/templates/reactionTypes.pug diff --git a/client/templates/includes/reactionsEditor.pug b/client/model-view/templates/reactionsView.pug similarity index 100% rename from client/templates/includes/reactionsEditor.pug rename to client/model-view/templates/reactionsView.pug diff --git a/client/templates/includes/ruleEditor.pug b/client/model-view/templates/rulesView.pug similarity index 100% rename from client/templates/includes/ruleEditor.pug rename to client/model-view/templates/rulesView.pug diff --git a/client/templates/includes/sbmlComponentEditor.pug b/client/model-view/templates/sbmlComponentsView.pug similarity index 100% rename from client/templates/includes/sbmlComponentEditor.pug rename to client/model-view/templates/sbmlComponentsView.pug diff --git a/client/templates/includes/spatialSpeciesEditor.pug b/client/model-view/templates/spatialSpeciesView.pug similarity index 100% rename from client/templates/includes/spatialSpeciesEditor.pug rename to client/model-view/templates/spatialSpeciesView.pug diff --git a/client/templates/includes/speciesTypeTemplate.pug b/client/model-view/templates/speciesTypeTemplate.pug similarity index 100% rename from client/templates/includes/speciesTypeTemplate.pug rename to client/model-view/templates/speciesTypeTemplate.pug diff --git a/client/templates/includes/speciesEditor.pug b/client/model-view/templates/speciesView.pug similarity index 100% rename from client/templates/includes/speciesEditor.pug rename to client/model-view/templates/speciesView.pug diff --git a/client/templates/includes/viewBoundaryCondition.pug b/client/model-view/templates/viewBoundaryCondition.pug similarity index 100% rename from client/templates/includes/viewBoundaryCondition.pug rename to client/model-view/templates/viewBoundaryCondition.pug diff --git a/client/templates/includes/viewEvents.pug b/client/model-view/templates/viewEvent.pug similarity index 100% rename from client/templates/includes/viewEvents.pug rename to client/model-view/templates/viewEvent.pug diff --git a/client/templates/includes/viewEventAssignment.pug b/client/model-view/templates/viewEventAssignment.pug similarity index 100% rename from client/templates/includes/viewEventAssignment.pug rename to client/model-view/templates/viewEventAssignment.pug diff --git a/client/templates/includes/viewFunctionDefinition.pug b/client/model-view/templates/viewFunctionDefinition.pug similarity index 100% rename from client/templates/includes/viewFunctionDefinition.pug rename to client/model-view/templates/viewFunctionDefinition.pug diff --git a/client/templates/includes/viewInitialCondition.pug b/client/model-view/templates/viewInitialCondition.pug similarity index 100% rename from client/templates/includes/viewInitialCondition.pug rename to client/model-view/templates/viewInitialCondition.pug diff --git a/client/templates/includes/viewParameters.pug b/client/model-view/templates/viewParameter.pug similarity index 100% rename from client/templates/includes/viewParameters.pug rename to client/model-view/templates/viewParameter.pug diff --git a/client/templates/includes/viewReactions.pug b/client/model-view/templates/viewReaction.pug similarity index 100% rename from client/templates/includes/viewReactions.pug rename to client/model-view/templates/viewReaction.pug diff --git a/client/templates/includes/viewRules.pug b/client/model-view/templates/viewRule.pug similarity index 100% rename from client/templates/includes/viewRules.pug rename to client/model-view/templates/viewRule.pug diff --git a/client/templates/includes/viewSpatialSpecies.pug b/client/model-view/templates/viewSpatialSpecie.pug similarity index 100% rename from client/templates/includes/viewSpatialSpecies.pug rename to client/model-view/templates/viewSpatialSpecie.pug diff --git a/client/templates/includes/viewSpecies.pug b/client/model-view/templates/viewSpecie.pug similarity index 100% rename from client/templates/includes/viewSpecies.pug rename to client/model-view/templates/viewSpecie.pug diff --git a/client/views/boundary-condition-view.js b/client/model-view/views/boundary-condition-view.js similarity index 84% rename from client/views/boundary-condition-view.js rename to client/model-view/views/boundary-condition-view.js index a91cf1b9fb..21b37c246e 100644 --- a/client/views/boundary-condition-view.js +++ b/client/model-view/views/boundary-condition-view.js @@ -18,12 +18,13 @@ along with this program. If not, see . let $ = require('jquery'); //support files -let modals = require('../modals'); +let app = require('../../app'); +let modals = require('../../modals'); //views let View = require('ampersand-view'); //templates -let editTemplate = require('../templates/includes/editBoundaryCondition.pug'); -let viewTemplate = require('../templates/includes/viewBoundaryCondition.pug'); +let editTemplate = require('../templates/editBoundaryCondition.pug'); +let viewTemplate = require('../templates/viewBoundaryCondition.pug'); module.exports = View.extend({ events: { @@ -33,19 +34,14 @@ module.exports = View.extend({ }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); - this.viewMode = attrs.viewMode ? attrs.viewMode : false + this.viewMode = attrs.viewMode ? attrs.viewMode : false; }, render: function (attrs, options) { this.template = this.viewMode ? viewTemplate : editTemplate; View.prototype.render.apply(this, arguments); - $(document).on('shown.bs.modal', function (e) { - $('[autofocus]', e.target).focus(); - }); - $(document).on('hide.bs.modal', '.modal', function (e) { - e.target.remove() - }); + app.documentSetup(); if(!this.model.annotation){ - $(this.queryByHook('edit-annotation-btn')).text('Add') + $(this.queryByHook('edit-annotation-btn')).text('Add'); } }, editAnnotation: function () { diff --git a/client/views/boundary-conditions-editor.js b/client/model-view/views/boundary-conditions-view.js similarity index 89% rename from client/views/boundary-conditions-editor.js rename to client/model-view/views/boundary-conditions-view.js index bfc9607a00..557273ce52 100644 --- a/client/views/boundary-conditions-editor.js +++ b/client/model-view/views/boundary-conditions-view.js @@ -19,16 +19,16 @@ along with this program. If not, see . let $ = require('jquery'); let path = require('path'); //support files -let app = require('../app'); -let tests = require('./tests'); -let Tooltips = require('../tooltips'); +let app = require('../../app'); +let tests = require('../../views/tests'); +let Tooltips = require('../../tooltips'); //views -let InputView = require('./input'); +let InputView = require('../../views/input'); let View = require('ampersand-view'); let SelectView = require('ampersand-select-view'); let BoundaryConditionView = require('./boundary-condition-view'); //templates -let template = require('../templates/includes/boundaryConditionsEditor.pug'); +let template = require('../templates/boundaryConditionsView.pug'); module.exports = View.extend({ template: template, @@ -78,13 +78,13 @@ module.exports = View.extend({ app.changeCollapseButtonText(this, e); }, handleAddBCClick: function (e) { - let endpoint = path.join(app.getApiPath(), "model/new-bc") + let endpoint = path.join(app.getApiPath(), "model/new-bc"); let self = this; if(this.newBC.property === "v") { - this.newBC.value = this.newBCVector + this.newBC.value = this.newBCVector; } let data = {model_path: this.collection.parent.directory, - kwargs: this.newBC} + kwargs: this.newBC}; app.postXHR(endpoint, data, { success: function (err, response, body) { self.collection.addNewBoundaryCondition(self.newBCName, body.expression); @@ -112,7 +112,7 @@ module.exports = View.extend({ $(this.queryByHook("new-bc-deterministic")).prop("disabled", true); }else{ let species = this.collection.parent.species.filter(function (specie) { - return specie.compID === Number(target) + return specie.compID === Number(target); })[0].name; this.newBC.property = null; this.newBC.species = species; @@ -129,13 +129,13 @@ module.exports = View.extend({ this.newBC[key] = this.validateNewBCCondition(key, value); }else if(key === "value") { if(e.delegateTarget.dataset.hook.endsWith("x")) { - this.newBCVector[0] = value === "" ? 0 : value + this.newBCVector[0] = value === "" ? 0 : value; }else if(e.delegateTarget.dataset.hook.endsWith("y")) { - this.newBCVector[1] = value === "" ? 0 : value + this.newBCVector[1] = value === "" ? 0 : value; }else if(e.delegateTarget.dataset.hook.endsWith("z")) { - this.newBCVector[2] = value === "" ? 0 : value + this.newBCVector[2] = value === "" ? 0 : value; }else{ - this.newBC[key] = value === "" ? null : value + this.newBC[key] = value === "" ? null : value; } } } @@ -150,12 +150,7 @@ module.exports = View.extend({ BoundaryConditionView, this.queryByHook("edit-boundary-conditions-list") ); - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); }, renderViewBoundaryConditionView: function () { if(this.viewBoundaryConditionView) { @@ -174,6 +169,7 @@ module.exports = View.extend({ this.queryByHook("view-boundary-conditions-list"), options ); + app.tooltipSetup(); }, resetNewBCViews: function () { $(this.queryByHook("new-bc-deterministic")).prop("checked", this.newBC.deterministic); @@ -194,19 +190,19 @@ module.exports = View.extend({ this.newBCName = ""; this.newBC = {"species": null, "property": "v", "value": null, "deterministic": true, "type_id": null, "xmin": null, "ymin": null, "zmin": null, "xmax": null, "ymax": null, "zmax": null}; - this.newBCVector = [0, 0, 0] + this.newBCVector = [0, 0, 0]; this.setConditions = []; }, toggleAddNewBCButton: function () { - let invalidName = this.newBCName === "" - let invalidValue = this.newBC.property === "v" ? this.newBCVector === [0, 0, 0] : this.newBC.value === null + let invalidName = this.newBCName === ""; + let invalidValue = this.newBC.property === "v" ? this.newBCVector === [0, 0, 0] : this.newBC.value === null; let disabled = invalidName || invalidValue || !this.setConditions.length; $(this.queryByHook("add-new-bc")).prop("disabled", disabled); }, update: function (e) {}, validateNewBCCondition: function(key, value) { if((value === 0 && key === "type_id") || value === "") { - value = null + value = null; if(this.setConditions.includes(key)){ let index = this.setConditions.indexOf(key); this.setConditions.splice(index, 1); @@ -233,11 +229,11 @@ module.exports = View.extend({ hook: "new-bc-target", prepareView: function (el) { let species = this.collection.parent.species.map(function (specie) { - return [specie.compID, specie.name] + return [specie.compID, specie.name]; }); - let properties = [["v", "Velocity"], ["nu", "Viscosity"], ["rho", "Density"]] + let properties = [["v", "Velocity"], ["nu", "Viscosity"], ["rho", "Density"]]; let options = [{groupName: "Properties", options: properties}, - {groupName: "Variables", options: species}] + {groupName: Boolean(species) ? "Variables" : "Variables (empty)", options: species}]; return new SelectView({ parent: this, required: false, @@ -256,7 +252,7 @@ module.exports = View.extend({ required: false, name: 'value', tests: tests.valueTests, - valueType: 'number', + valueType: 'number' }); } }, @@ -308,7 +304,7 @@ module.exports = View.extend({ name: 'xmin', tests: tests.valueTests, valueType: 'number', - value: this.newBC.xmin, + value: this.newBC.xmin }); } }, @@ -321,7 +317,7 @@ module.exports = View.extend({ name: 'ymin', tests: tests.valueTests, valueType: 'number', - value: this.newBC.ymin, + value: this.newBC.ymin }); } }, @@ -334,7 +330,7 @@ module.exports = View.extend({ name: 'zmin', tests: tests.valueTests, valueType: 'number', - value: this.newBC.zmin, + value: this.newBC.zmin }); } }, @@ -347,7 +343,7 @@ module.exports = View.extend({ name: 'xmax', tests: tests.valueTests, valueType: 'number', - value: this.newBC.xmax, + value: this.newBC.xmax }); } }, @@ -360,7 +356,7 @@ module.exports = View.extend({ name: 'ymax', tests: tests.valueTests, valueType: 'number', - value: this.newBC.ymax, + value: this.newBC.ymax }); } }, @@ -373,7 +369,7 @@ module.exports = View.extend({ name: 'zmax', tests: tests.valueTests, valueType: 'number', - value: this.newBC.zmax, + value: this.newBC.zmax }); } }, @@ -386,7 +382,7 @@ module.exports = View.extend({ name: 'type', tests: tests.valueTests, valueType: 'number', - value: this.newBC.type_id, + value: this.newBC.type_id }); } } diff --git a/client/views/component-types.js b/client/model-view/views/component-types.js similarity index 91% rename from client/views/component-types.js rename to client/model-view/views/component-types.js index f96375fa28..f04a3d4247 100644 --- a/client/views/component-types.js +++ b/client/model-view/views/component-types.js @@ -20,8 +20,8 @@ let $ = require("jquery"); //views var View = require('ampersand-view'); //templates -var specTypeTemplate = require('../templates/includes/speciesTypeTemplate.pug'); -var reacTypeTemplate = require('../templates/includes/reactionTypeTemplate.pug'); +var specTypeTemplate = require('../templates/speciesTypeTemplate.pug'); +var reacTypeTemplate = require('../templates/reactionTypeTemplate.pug'); module.exports = View.extend({ events: { diff --git a/client/views/domain-viewer.js b/client/model-view/views/domain-viewer.js similarity index 93% rename from client/views/domain-viewer.js rename to client/model-view/views/domain-viewer.js index 2ff51bcc60..619347c0f5 100644 --- a/client/views/domain-viewer.js +++ b/client/model-view/views/domain-viewer.js @@ -20,16 +20,16 @@ var $ = require('jquery'); let path = require('path'); var _ = require('underscore'); //support files -var app = require('../app'); -var Plotly = require('../lib/plotly'); -var Tooltips = require('../tooltips'); +var app = require('../../app'); +var Plotly = require('../../lib/plotly'); +var Tooltips = require('../../tooltips'); //views var View = require('ampersand-view'); -var TypesViewer = require('./edit-domain-type'); +var TypesViewer = require('../../views/edit-domain-type'); var SelectView = require('ampersand-select-view'); -var ParticleViewer = require('./view-particle'); +var ParticleViewer = require('../../views/view-particle'); //templates -var template = require('../templates/includes/domainViewer.pug'); +var template = require('../templates/domainViewer.pug'); module.exports = View.extend({ template: template, @@ -84,7 +84,7 @@ module.exports = View.extend({ this.toggleDomainError(); } this.renderTypesViewer(); - this.parent.renderParticleViewer(null); + this.parent.parent.renderParticleViewer(null); let endpoint = path.join(app.getApiPath(), "spatial-model/domain-plot") + queryStr; app.getXHR(endpoint, { always: function (err, response, body) { @@ -119,7 +119,7 @@ module.exports = View.extend({ }, reloadDomain: function (domainPath) { if(this.domainPath !== domainPath || domainPath === "viewing") { - var el = this.parent.queryByHook("domain-plot-container"); + var el = this.parent.parent.queryByHook("domain-plot-container"); el.removeListener('plotly_click', this.selectParticle); Plotly.purge(el); this.plot = null; @@ -193,14 +193,14 @@ module.exports = View.extend({ }, displayDomain: function () { let self = this; - var domainPreview = this.parent.queryByHook("domain-plot-container"); + var domainPreview = this.parent.parent.queryByHook("domain-plot-container"); Plotly.newPlot(domainPreview, this.plot); domainPreview.on('plotly_click', _.bind(this.selectParticle, this)); }, selectParticle: function (data) { let point = data.points[0]; let particle = this.model.particles.get(point.id, "particle_id"); - this.parent.renderParticleViewer(particle); + this.parent.parent.renderParticleViewer(particle); }, editDomain: function (e) { var queryStr = "?path=" + this.parent.model.directory; diff --git a/client/views/edit-custom-stoich-specie.js b/client/model-view/views/edit-custom-stoich-specie.js similarity index 98% rename from client/views/edit-custom-stoich-specie.js rename to client/model-view/views/edit-custom-stoich-specie.js index 0e842387eb..bbc71ca80e 100644 --- a/client/views/edit-custom-stoich-specie.js +++ b/client/model-view/views/edit-custom-stoich-specie.js @@ -20,7 +20,7 @@ var $ = require('jquery'); //views var SelectView = require('ampersand-select-view'); //templates -var template = require('../templates/includes/editCustomStoichSpecie.pug'); +var template = require('../templates/editCustomStoichSpecie.pug'); module.exports = SelectView.extend({ // SelectView expects a string template, so pre-render it diff --git a/client/views/edit-stoich-specie.js b/client/model-view/views/edit-stoich-specie.js similarity index 96% rename from client/views/edit-stoich-specie.js rename to client/model-view/views/edit-stoich-specie.js index 4f276620aa..b4acc31af6 100644 --- a/client/views/edit-stoich-specie.js +++ b/client/model-view/views/edit-stoich-specie.js @@ -20,7 +20,7 @@ var $ = require('jquery'); //views var SelectView = require('ampersand-select-view'); //templates -var template = require('../templates/includes/editStoichSpecie.pug'); +var template = require('../templates/editStoichSpecie.pug'); module.exports = SelectView.extend({ // SelectView expects a string template, so pre-render it diff --git a/client/views/edit-event-assignment.js b/client/model-view/views/event-assignment-view.js similarity index 78% rename from client/views/edit-event-assignment.js rename to client/model-view/views/event-assignment-view.js index 8bb53ad728..69193ac7ec 100644 --- a/client/views/edit-event-assignment.js +++ b/client/model-view/views/event-assignment-view.js @@ -16,16 +16,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); //support files -let app = require('../app'); +let app = require('../../app'); //views -var View = require('ampersand-view'); -var InputView = require('./input'); -var SelectView = require('ampersand-select-view'); +let InputView = require('../../views/input'); +let View = require('ampersand-view'); +let SelectView = require('ampersand-select-view'); //templates -var editTemplate = require('../templates/includes/editEventAssignment.pug'); -var viewTemplate = require('../templates/includes/viewEventAssignment.pug'); +let editTemplate = require('../templates/editEventAssignment.pug'); +let viewTemplate = require('../templates/viewEventAssignment.pug'); module.exports = View.extend({ events: { @@ -41,28 +41,24 @@ module.exports = View.extend({ this.template = this.viewMode ? viewTemplate : editTemplate; View.prototype.render.apply(this, arguments); }, - update: function () { - }, - updateValid: function () { - }, - removeAssignment: function () { - this.remove(); - this.collection.removeEventAssignment(this.model) - this.collection.parent.collection.trigger('change') - }, getOptions: function () { var species = this.model.collection.parent.collection.parent.species; var parameters = this.model.collection.parent.collection.parent.parameters; var specs = species.map(function (specie) { - return [specie.compID, specie.name] + return [specie.compID, specie.name]; }); var params = parameters.map(function (parameter) { - return [parameter.compID, parameter.name] + return [parameter.compID, parameter.name]; }); - let options = [{groupName: "Variables", options: specs}, - {groupName: "Parameters", options: params}] + let options = [{groupName: Boolean(specs) ? "Variables" : "Variables (empty)", options: specs}, + {groupName: Boolean(params) ? "Parameters" : "Parameters (empty)", options: params}]; return options; }, + removeAssignment: function () { + this.remove(); + this.collection.removeEventAssignment(this.model); + this.collection.parent.collection.trigger('change'); + }, selectAssignmentVariable: function (e) { var species = this.model.collection.parent.collection.parent.species; var parameters = this.model.collection.parent.collection.parent.parameters; @@ -83,6 +79,8 @@ module.exports = View.extend({ this.updateViewer(); this.model.collection.parent.collection.trigger('change'); }, + update: function () {}, + updateValid: function () {}, updateViewer: function () { this.model.collection.parent.trigger('change'); }, @@ -97,9 +95,9 @@ module.exports = View.extend({ placeholder: "---No Expression Entered---", modelKey: 'expression', valueType: 'string', - value: this.model.expression, + value: this.model.expression }); - }, + } }, variableSelectView: { hook: 'event-assignment-variable', @@ -110,7 +108,7 @@ module.exports = View.extend({ required: true, idAttributes: 'cid', groupOptions: options, - value: this.model.variable.compID, + value: this.model.variable.compID }); } } diff --git a/client/views/event-assignments-editor.js b/client/model-view/views/event-assignments-view.js similarity index 93% rename from client/views/event-assignments-editor.js rename to client/model-view/views/event-assignments-view.js index 3640c137e9..7d604f8ac7 100644 --- a/client/views/event-assignments-editor.js +++ b/client/model-view/views/event-assignments-view.js @@ -18,12 +18,12 @@ along with this program. If not, see . let $ = require('jquery'); //support files -let app = require('../app'); +let app = require('../../app'); //views var View = require('ampersand-view'); -var EditEventAssignment = require('./edit-event-assignment'); +var EditEventAssignment = require('./event-assignment-view'); //templates -var template = require('../templates/includes/eventAssignmentsEditor.pug'); +var template = require('../templates/eventAssignmentsView.pug'); module.exports = View.extend({ template: template, diff --git a/client/views/event-details.js b/client/model-view/views/event-details.js similarity index 80% rename from client/views/event-details.js rename to client/model-view/views/event-details.js index a4cf72f6c9..b6ea87febd 100644 --- a/client/views/event-details.js +++ b/client/model-view/views/event-details.js @@ -16,16 +16,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); //support files -let app = require('../app'); -var tests = require('./tests'); +let app = require('../../app'); +let tests = require('../../views/tests'); //views -var View = require('ampersand-view'); -var InputView = require('./input'); -var EventAssignment = require('./event-assignments-editor'); +let InputView = require('../../views/input'); +let View = require('ampersand-view'); +let EventAssignment = require('./event-assignments-view'); //templates -var template = require('../templates/includes/eventDetails.pug'); +let template = require('../templates/eventDetails.pug'); module.exports = View.extend({ template: template, @@ -33,12 +33,12 @@ module.exports = View.extend({ 'model.initialValue': { hook: 'event-trigger-init-value', type: 'booleanAttribute', - name: 'checked', + name: 'checked' }, 'model.persistent': { hook: 'event-trigger-persistent', type: 'booleanAttribute', - name: 'checked', + name: 'checked' }, }, events: { @@ -46,7 +46,7 @@ module.exports = View.extend({ 'change [data-hook=event-trigger-persistent]' : 'setTriggerPersistent', 'change [data-hook=edit-trigger-time]' : 'setUseValuesFromTriggerTime', 'change [data-hook=edit-assignment-time]' : 'setUseValuesFromTriggerTime', - 'click [data-hook=advanced-event-button]' : 'changeCollapseButtonText', + 'click [data-hook=advanced-event-button]' : 'changeCollapseButtonText' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); @@ -55,25 +55,25 @@ module.exports = View.extend({ View.prototype.render.apply(this, arguments); this.renderEventAssignments(); if(this.model.useValuesFromTriggerTime){ - $(this.queryByHook('edit-trigger-time')).prop('checked', true) + $(this.queryByHook('edit-trigger-time')).prop('checked', true); }else{ - $(this.queryByHook('edit-assignment-time')).prop('checked', true) + $(this.queryByHook('edit-assignment-time')).prop('checked', true); } - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); - }); + app.tooltipSetup(); }, - update: function () { + changeCollapseButtonText: function (e) { + app.changeCollapseButtonText(this, e); }, - updateValid: function () { + openAdvancedSection: function () { + if(this.model.advanced_error && !$(this.queryByHook("advanced-event-section")).hasClass('show')) { + let advCollapseBtn = $(this.queryByHook("advanced-event-button")); + advCollapseBtn.click(); + advCollapseBtn.html('-'); + } }, renderEventAssignments: function () { if(this.eventAssignmentsView){ - this.eventAssignmentsView.remove() + this.eventAssignmentsView.remove(); } this.eventAssignmentsView = new EventAssignment({ collection: this.model.eventAssignments, @@ -81,13 +81,6 @@ module.exports = View.extend({ }); app.registerRenderSubview(this, this.eventAssignmentsView, 'event-assignments'); }, - openAdvancedSection: function () { - if(this.model.advanced_error && !$(this.queryByHook("advanced-event-section")).hasClass('show')) { - let advCollapseBtn = $(this.queryByHook("advanced-event-button")) - advCollapseBtn.click() - advCollapseBtn.html('-') - } - }, setTriggerInitialValue: function (e) { this.model.initialValue = e.target.checked; }, @@ -97,9 +90,8 @@ module.exports = View.extend({ setUseValuesFromTriggerTime: function (e) { this.model.useValuesFromTriggerTime = e.target.dataset.name === "trigger"; }, - changeCollapseButtonText: function (e) { - app.changeCollapseButtonText(this, e); - }, + update: function () {}, + updateValid: function () {}, subviews: { inputDelay: { hook: 'event-delay', @@ -111,9 +103,9 @@ module.exports = View.extend({ placeholder: '---No Expression Entered---', modelKey: 'delay', valueType: 'string', - value: this.model.delay, + value: this.model.delay }); - }, + } }, inputPriority: { hook: 'event-priority', @@ -124,9 +116,9 @@ module.exports = View.extend({ name: 'priority', modelKey: 'priority', valueType: 'string', - value: this.model.priority, + value: this.model.priority }); - }, + } }, inputTriggerExpression: { hook: 'event-trigger-expression', @@ -138,9 +130,9 @@ module.exports = View.extend({ placeholder: '---No Expression Entered---', modelKey: 'triggerExpression', valueType: 'string', - value: this.model.triggerExpression, + value: this.model.triggerExpression }); - }, - }, - }, + } + } + } }); \ No newline at end of file diff --git a/client/views/event-listings.js b/client/model-view/views/event-listing.js similarity index 72% rename from client/views/event-listings.js rename to client/model-view/views/event-listing.js index 0a7c7866fe..7776033d03 100644 --- a/client/views/event-listings.js +++ b/client/model-view/views/event-listing.js @@ -16,19 +16,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); let _ = require('underscore'); //support files -let app = require('../app'); -var tests = require('./tests'); -var modals = require('../modals'); +let app = require('../../app'); +let tests = require('../../views/tests'); +let modals = require('../../modals'); //views -var View = require('ampersand-view'); -var InputView = require('./input'); -var EventAssignment = require('./event-assignments-editor'); +let InputView = require('../../views/input'); +let View = require('ampersand-view'); +let EventAssignment = require('./event-assignments-view'); //templates -var editTemplate = require('../templates/includes/eventListings.pug'); -let viewTemplate = require('../templates/includes/viewEvents.pug'); +let viewTemplate = require('../templates/viewEvent.pug'); +let editTemplate = require('../templates/eventListing.pug'); module.exports = View.extend({ bindings: { @@ -41,18 +41,18 @@ module.exports = View.extend({ 'model.initialValue': { hook: 'event-trigger-init-value', type: 'booleanAttribute', - name: 'checked', + name: 'checked' }, 'model.persistent': { hook: 'event-trigger-persistent', type: 'booleanAttribute', - name: 'checked', + name: 'checked' } }, events: { 'click [data-hook=select]' : 'selectEvent', 'click [data-hook=edit-annotation-btn]' : 'editAnnotation', - 'click [data-hook=remove]' : 'removeEvent', + 'click [data-hook=remove]' : 'removeEvent' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); @@ -66,17 +66,11 @@ module.exports = View.extend({ render: function () { this.template = this.viewMode ? viewTemplate : editTemplate; View.prototype.render.apply(this, arguments); - $(document).on('shown.bs.modal', function (e) { - $('[autofocus]', e.target).focus(); - }); - $(document).on('hide.bs.modal', '.modal', function (e) { - e.target.remove() - }); + app.documentSetup(); if(!this.model.annotation){ $(this.queryByHook('edit-annotation-btn')).text('Add'); } if(this.viewMode) { - this.renderViewEventAssignments(); if(this.model.useValuesFromTriggerTime) { $(this.queryByHook("view-trigger-time")).prop('checked', true); }else{ @@ -84,20 +78,13 @@ module.exports = View.extend({ } } }, - update: function () { - }, - updateValid: function () { - }, - selectEvent: function (e) { - this.model.collection.trigger("select", this.model); - }, editAnnotation: function () { - var self = this; - var name = this.model.name; - var annotation = this.model.annotation; if(document.querySelector('#eventAnnotationModal')) { document.querySelector('#eventAnnotationModal').remove(); } + let self = this; + let name = this.model.name; + let annotation = this.model.annotation; let modal = $(modals.annotationModalHtml("event", name, annotation)).modal(); let okBtn = document.querySelector('#eventAnnotationModal .ok-model-btn'); let input = document.querySelector('#eventAnnotationModal #eventAnnotationInput'); @@ -117,17 +104,11 @@ module.exports = View.extend({ this.remove(); this.collection.removeEvent(this.model); }, - renderViewEventAssignments: function () { - if(this.viewEventAssignmentsView){ - this.viewEventAssignmentsView.remove() - } - this.viewEventAssignmentsView = new EventAssignment({ - collection: this.model.eventAssignments, - tooltips: this.parent.tooltips, - readOnly: true - }); - app.registerRenderSubview(this, this.viewEventAssignmentsView, 'assignment-viewer'); + selectEvent: function (e) { + this.model.collection.trigger("select", this.model); }, + update: function () {}, + updateValid: function () {}, updateViewer: function () { this.parent.renderViewEventListingView(); }, @@ -139,13 +120,22 @@ module.exports = View.extend({ parent: this, required: true, name: 'name', - label: '', tests: tests.nameTests, modelKey: 'name', valueType: 'string', - value: this.model.name, + value: this.model.name }); - }, + } }, - }, + viewEventAssignmentsView: { + hook: "assignment-viewer", + prepareView: function (el) { + return new EventAssignment({ + collection: this.model.eventAssignments, + tooltips: this.parent.tooltips, + readOnly: true + }); + } + } + } }); \ No newline at end of file diff --git a/client/views/events-editor.js b/client/model-view/views/events-view.js similarity index 71% rename from client/views/events-editor.js rename to client/model-view/views/events-view.js index ff6b3b34f8..629470944a 100644 --- a/client/views/events-editor.js +++ b/client/model-view/views/events-view.js @@ -16,29 +16,28 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var ViewSwitcher = require('ampersand-view-switcher'); -var $ = require('jquery'); +let $ = require('jquery'); //support files -let app = require('../app'); -var Tooltips = require("../tooltips"); +let app = require('../../app'); +let Tooltips = require("../../tooltips"); //views -var View = require('ampersand-view'); -var EventListings = require('./event-listings'); -var EventDetails = require('./event-details'); +let View = require('ampersand-view'); +let EventDetails = require('./event-details'); +let EventListings = require('./event-listing'); +let ViewSwitcher = require('ampersand-view-switcher'); //templates -var template = require('../templates/includes/eventsEditor.pug'); +let template = require('../templates/eventsView.pug'); module.exports = View.extend({ template: template, events: { 'click [data-hook=add-event]' : 'addEvent', - 'click [data-hook=save-events]' : 'switchToViewMode', - 'click [data-hook=collapse]' : 'changeCollapseButtonText', + 'click [data-hook=collapse]' : 'changeCollapseButtonText' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); this.readOnly = attrs.readOnly ? attrs.readOnly : false; - this.tooltips = Tooltips.eventsEditor + this.tooltips = Tooltips.eventsEditor; if(!this.readOnly) { this.collection.on("select", function (event) { this.setSelectedEvent(event); @@ -47,11 +46,12 @@ module.exports = View.extend({ this.collection.on("remove", function (event) { // Select the last event by default // But only if there are other events other than the one we're removing - if (event.detailsView) + if (event.detailsView){ event.detailsView.remove(); + } this.collection.removeEvent(event); if (this.collection.length) { - var selected = this.collection.at(this.collection.length-1); + let selected = this.collection.at(this.collection.length-1); this.collection.trigger("select", selected); } }, this); @@ -74,19 +74,29 @@ module.exports = View.extend({ this.renderEditEventListingsView(); this.detailsContainer = this.queryByHook('event-details-container'); this.detailsViewSwitcher = new ViewSwitcher({ - el: this.detailsContainer, + el: this.detailsContainer }); if(this.collection.length) { this.setSelectedEvent(this.collection.at(0)); this.collection.trigger("select", this.selectedEvent); } - this.toggleAddEventButton() + this.toggleAddEventButton(); } this.renderViewEventListingView(); }, - update: function () { + addEvent: function () { + let event = this.collection.addEvent(); + event.detailsView = this.newDetailsView(event); + this.collection.trigger("select", event); + app.tooltipSetup(); }, - updateValid: function () { + changeCollapseButtonText: function (e) { + app.changeCollapseButtonText(this, e); + }, + newDetailsView: function (event) { + let detailsView = new EventDetails({ model: event }); + detailsView.parent = this; + return detailsView; }, renderEditEventListingsView: function () { if(this.editEventListingsView){ @@ -97,12 +107,7 @@ module.exports = View.extend({ EventListings, this.queryByHook('edit-event-listing-container') ); - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); }, renderViewEventListingView: function () { if(this.viewEventListingsView) { @@ -121,55 +126,28 @@ module.exports = View.extend({ this.queryByHook('view-event-listing-container'), options ); - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); }, - toggleAddEventButton: function () { - this.collection.map(function (event) { - if(event.detailsView && event.selected){ - event.detailsView.renderEventAssignments(); - } - }) - var numSpecies = this.collection.parent.species.length; - var numParameters = this.collection.parent.parameters.length; - var disabled = numSpecies <= 0 && numParameters <= 0 - $(this.queryByHook('add-event')).prop('disabled', disabled); + setDetailsView: function (event) { + event.detailsView = event.detailsView || this.newDetailsView(event); + this.detailsViewSwitcher.set(event.detailsView); }, setSelectedEvent: function (event) { this.collection.each(function (m) { m.selected = false; }); event.selected = true; this.selectedEvent = event; }, - setDetailsView: function (event) { - event.detailsView = event.detailsView || this.newDetailsView(event); - this.detailsViewSwitcher.set(event.detailsView); - }, - addEvent: function () { - var event = this.collection.addEvent(); - event.detailsView = this.newDetailsView(event); - this.collection.trigger("select", event); - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); + toggleAddEventButton: function () { + this.collection.map(function (event) { + if(event.detailsView && event.selected){ + event.detailsView.renderEventAssignments(); + } }); + let numSpecies = this.collection.parent.species.length; + let numParameters = this.collection.parent.parameters.length; + let disabled = numSpecies <= 0 && numParameters <= 0; + $(this.queryByHook('add-event')).prop('disabled', disabled); }, - newDetailsView: function (event) { - var detailsView = new EventDetails({ model: event }); - detailsView.parent = this; - return detailsView - }, - switchToViewMode: function (e) { - this.parent.modelStateButtons.clickSaveHandler(e); - this.parent.renderEventsView(mode="view"); - }, - changeCollapseButtonText: function (e) { - app.changeCollapseButtonText(this, e); - }, -}) \ No newline at end of file + update: function () {}, + updateValid: function () {} +}); \ No newline at end of file diff --git a/client/views/edit-function-definition.js b/client/model-view/views/function-definition-view.js similarity index 83% rename from client/views/edit-function-definition.js rename to client/model-view/views/function-definition-view.js index d582b9dba6..dd6f3d6f89 100644 --- a/client/views/edit-function-definition.js +++ b/client/model-view/views/function-definition-view.js @@ -16,19 +16,20 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); //support files -var modals = require('../modals'); +let app = require('../../app'); +let modals = require('../../modals'); //views -var View = require('ampersand-view'); +let View = require('ampersand-view'); //templates -var editTemplate = require('../templates/includes/editFunctionDefinition.pug'); -let viewTemplate = require('../templates/includes/viewFunctionDefinition.pug'); +let editTemplate = require('../templates/editFunctionDefinition.pug'); +let viewTemplate = require('../templates/viewFunctionDefinition.pug'); module.exports = View.extend({ events: { 'click [data-hook=remove]' : 'removeFunctionDefinition', - 'click [data-hook=edit-annotation-btn]' : 'editAnnotation', + 'click [data-hook=edit-annotation-btn]' : 'editAnnotation' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); @@ -37,9 +38,7 @@ module.exports = View.extend({ render: function () { this.template = this.viewMode ? viewTemplate : editTemplate; View.prototype.render.apply(this, arguments); - $(document).on('hide.bs.modal', '.modal', function (e) { - e.target.remove() - }); + app.documentSetup(); }, editAnnotation: function () { var self = this; @@ -65,5 +64,5 @@ module.exports = View.extend({ }, removeFunctionDefinition: function () { this.model.collection.remove(this.model); - }, + } }); \ No newline at end of file diff --git a/client/views/edit-initial-condition.js b/client/model-view/views/initial-condition-view.js similarity index 89% rename from client/views/edit-initial-condition.js rename to client/model-view/views/initial-condition-view.js index 80b9489814..bd45098172 100644 --- a/client/views/edit-initial-condition.js +++ b/client/model-view/views/initial-condition-view.js @@ -19,17 +19,17 @@ along with this program. If not, see . let $ = require('jquery'); let _ = require('underscore'); //support files -let app = require('../app'); -var tests = require('./tests'); -let modals = require('../modals'); +let app = require('../../app'); +let tests = require('../../views/tests'); +let modals = require('../../modals'); //views -var View = require('ampersand-view'); -var InputView = require('./input'); -var SelectView = require('ampersand-select-view'); -var TypesView = require('./component-types'); +let InputView = require('../../views/input'); +let View = require('ampersand-view'); +let TypesView = require('./component-types'); +let SelectView = require('ampersand-select-view'); //templates -let editTemplate = require('../templates/includes/editInitialCondition.pug'); -let viewTemplate = require('../templates/includes/viewInitialCondition.pug'); +let editTemplate = require('../templates/editInitialCondition.pug'); +let viewTemplate = require('../templates/viewInitialCondition.pug'); module.exports = View.extend({ events: { @@ -47,31 +47,26 @@ module.exports = View.extend({ this.types = []; this.model.types.forEach(function (index) { let type = self.model.collection.parent.domain.types.get(index, "typeID"); - self.types.push(type.name) + self.types.push(type.name); }); } }, render: function () { this.template = this.viewMode ? viewTemplate : editTemplate; View.prototype.render.apply(this, arguments); + app.documentSetup(); if(!this.viewMode) { this.model.on('change', _.bind(this.updateViewer, this)); } - $(document).on('shown.bs.modal', function (e) { - $('[autofocus]', e.target).focus(); - }); - $(document).on('hide.bs.modal', '.modal', function (e) { - e.target.remove() - }); if(!this.model.annotation){ - $(this.queryByHook('edit-annotation-btn')).text('Add') + $(this.queryByHook('edit-annotation-btn')).text('Add'); } this.toggleDetailsView(); }, editAnnotation: function () { - var self = this; - var name = this.model.name; - var annotation = this.model.annotation; + let self = this; + let name = this.model.name; + let annotation = this.model.annotation; if(document.querySelector('#initialConditionAnnotationModal')) { document.querySelector('#initialConditionAnnotationModal').remove(); } @@ -115,11 +110,11 @@ module.exports = View.extend({ }, toggleDetailsView: function () { if(this.model.icType === "Place") { - $(this.queryByHook("scatter-details")).css("display", "none") - $(this.queryByHook("place-details")).css("display", "block") + $(this.queryByHook("scatter-details")).css("display", "none"); + $(this.queryByHook("place-details")).css("display", "block"); }else { - $(this.queryByHook("place-details")).css("display", "none") - $(this.queryByHook("scatter-details")).css("display", "block") + $(this.queryByHook("place-details")).css("display", "none"); + $(this.queryByHook("scatter-details")).css("display", "block"); } }, update: function () {}, diff --git a/client/views/initial-conditions-editor.js b/client/model-view/views/initial-conditions-view.js similarity index 81% rename from client/views/initial-conditions-editor.js rename to client/model-view/views/initial-conditions-view.js index 54a9c1d4f2..c842157d1e 100644 --- a/client/views/initial-conditions-editor.js +++ b/client/model-view/views/initial-conditions-view.js @@ -16,15 +16,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); //support files -let app = require('../app'); -let Tooltips = require('../tooltips'); +let app = require('../../app'); +let Tooltips = require('../../tooltips'); //views -var View = require('ampersand-view'); -var EditInitialCondition = require('./edit-initial-condition'); +let View = require('ampersand-view'); +let InitialConditionView = require('./initial-condition-view'); //templates -var template = require('../templates/includes/initialConditionsEditor.pug'); +let template = require('../templates/initialConditionsView.pug'); module.exports = View.extend({ template: template, @@ -73,23 +73,18 @@ module.exports = View.extend({ }, renderEditInitialConditionsView: function () { if(this.editInitialConditionView) { - this.editInitialConditionView.remove() + this.editInitialConditionView.remove(); } this.editInitialConditionView = this.renderCollection( this.collection, - EditInitialCondition, + InitialConditionView, this.queryByHook('edit-initial-conditions-collection') ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); }, renderViewInitialConditionsView: function () { if(this.viewInitialConditionView) { - this.viewInitialConditionView.remove() + this.viewInitialConditionView.remove(); } this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0; if(!this.containsMdlWithAnn) { @@ -100,16 +95,11 @@ module.exports = View.extend({ let options = {viewOptions: {viewMode: true}}; this.viewInitialConditionView = this.renderCollection( this.collection, - EditInitialCondition, + InitialConditionView, this.queryByHook('view-initial-conditions-collection'), options ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); }, update: function () {}, updateValid: function () {} diff --git a/client/views/edit-parameter.js b/client/model-view/views/parameter-view.js similarity index 75% rename from client/views/edit-parameter.js rename to client/model-view/views/parameter-view.js index bc2bec13e9..0dd0df630a 100644 --- a/client/views/edit-parameter.js +++ b/client/model-view/views/parameter-view.js @@ -16,60 +16,48 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); let _ = require('underscore'); //support files -var tests = require('./tests'); -var modals = require('../modals') +let app = require('../../app'); +let tests = require('../../views/tests'); +let modals = require('../../modals'); //views -var View = require('ampersand-view'); -var InputView = require('./input'); +let InputView = require('../../views/input'); +let View = require('ampersand-view'); //templates -var editTemplate = require('../templates/includes/editParameter.pug'); -let viewTemplate = require('../templates/includes/viewParameters.pug'); +let editTemplate = require('../templates/editParameter.pug'); +let viewTemplate = require('../templates/viewParameter.pug'); module.exports = View.extend({ bindings: { 'model.inUse': { hook: 'remove', type: 'booleanAttribute', - name: 'disabled', - }, + name: 'disabled' + } }, events: { 'click [data-hook=edit-annotation-btn]' : 'editAnnotation', 'click [data-hook=remove]' : 'removeParameter', - 'change [data-hook=input-name-container]' : 'setParameterName', + 'change [data-hook=input-name-container]' : 'setParameterName' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); - this.previousName = this.model.name + this.previousName = this.model.name; this.viewMode = attrs.viewMode ? attrs.viewMode : false; }, render: function () { this.template = this.viewMode ? viewTemplate : editTemplate; View.prototype.render.apply(this, arguments); + app.documentSetup(); if(!this.viewMode){ - this.model.on('change', _.bind(this.updateViewer, this)) + this.model.on('change', _.bind(this.updateViewer, this)); } - $(document).on('shown.bs.modal', function (e) { - $('[autofocus]', e.target).focus(); - }); - $(document).on('hide.bs.modal', '.modal', function (e) { - e.target.remove() - }); if(!this.model.annotation){ - $(this.queryByHook('edit-annotation-btn')).text('Add') + $(this.queryByHook('edit-annotation-btn')).text('Add'); } }, - update: function () { - }, - updateValid: function () { - }, - removeParameter: function () { - this.remove(); - this.collection.removeParameter(this.model); - }, editAnnotation: function () { var self = this; var name = this.model.name; @@ -92,18 +80,24 @@ module.exports = View.extend({ modal.modal('hide'); }); }, + removeParameter: function () { + this.remove(); + this.collection.removeParameter(this.model); + }, setParameterName: function (e) { if(!e.target.value.trim()) { - this.model.name = this.previousName - this.parent.renderEditParameter() + this.model.name = this.previousName; + this.parent.renderEditParameter(); }else{ this.previousName = this.model.name this.model.collection.trigger('update-parameters', this.model.compID, this.model); - this.model.collection.trigger('remove') + this.model.collection.trigger('remove'); } }, + update: function () {}, + updateValid: function () {}, updateViewer: function () { - this.parent.renderViewParameter() + this.parent.renderViewParameter(); }, subviews: { inputName: { @@ -113,13 +107,12 @@ module.exports = View.extend({ parent: this, required: true, name: 'name', - label: '', tests: tests.nameTests, modelKey: 'name', valueType: 'string', - value: this.model.name, + value: this.model.name }); - }, + } }, inputValue: { hook: 'input-value-container', @@ -128,13 +121,12 @@ module.exports = View.extend({ parent: this, required: true, name: 'expression', - label: '', tests: tests.valueTests, modelKey: 'expression', valueType: 'number', - value: this.model.expression, + value: this.model.expression }); - }, - }, - }, + } + } + } }); \ No newline at end of file diff --git a/client/views/parameters-editor.js b/client/model-view/views/parameters-view.js similarity index 81% rename from client/views/parameters-editor.js rename to client/model-view/views/parameters-view.js index d7623c1a93..13bdf608a9 100644 --- a/client/views/parameters-editor.js +++ b/client/model-view/views/parameters-view.js @@ -16,15 +16,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); //support files -let app = require('../app'); -var Tooltips = require('../tooltips'); +let app = require('../../app'); +let Tooltips = require('../../tooltips'); //views -var View = require('ampersand-view'); -var EditParameterView = require('./edit-parameter'); +let View = require('ampersand-view'); +let EditParameterView = require('./parameter-view'); //templates -var template = require('../templates/includes/parametersEditor.pug'); +let template = require('../templates/parametersView.pug'); module.exports = View.extend({ template: template, @@ -33,10 +33,10 @@ module.exports = View.extend({ 'click [data-hook=collapse]' : 'changeCollapseButtonText', }, initialize: function (attrs, options) { - var self = this; View.prototype.initialize.apply(this, arguments); this.readOnly = attrs.readOnly ? attrs.readOnly : false; - this.tooltips = Tooltips.parametersEditor + this.tooltips = Tooltips.parametersEditor; + let self = this; this.collection.on('update-parameters', function (compID, parameter) { self.collection.parent.reactions.map(function (reaction) { if(reaction.rate && reaction.rate.compID === compID){ @@ -57,7 +57,7 @@ module.exports = View.extend({ rule.variable = parameter; } }); - self.parent.renderRulesView(); + self.parent.rulesView.renderEditRules(); }); }, render: function () { @@ -76,9 +76,12 @@ module.exports = View.extend({ } this.renderViewParameter(); }, - update: function () { + addParameter: function () { + this.collection.addParameter(); + app.tooltipSetup(); }, - updateValid: function () { + changeCollapseButtonText: function (e) { + app.changeCollapseButtonText(this, e); }, renderEditParameter: function () { if(this.editParameterView){ @@ -89,12 +92,6 @@ module.exports = View.extend({ EditParameterView, this.queryByHook('edit-parameter-list') ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); }, renderViewParameter: function () { if(this.viewParameterView) { @@ -114,17 +111,6 @@ module.exports = View.extend({ options ); }, - addParameter: function () { - this.collection.addParameter(); - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); - }); - }, - changeCollapseButtonText: function (e) { - app.changeCollapseButtonText(this, e); - }, + update: function () {}, + updateValid: function () {} }); \ No newline at end of file diff --git a/client/views/reactant-product.js b/client/model-view/views/reactant-product.js similarity index 69% rename from client/views/reactant-product.js rename to client/model-view/views/reactant-product.js index 8a982bcc03..bdd1bfc183 100644 --- a/client/views/reactant-product.js +++ b/client/model-view/views/reactant-product.js @@ -16,16 +16,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); //models -var StoichSpecie = require('../models/stoich-specie'); +let StoichSpecie = require('../../models/stoich-specie'); //views -var View = require('ampersand-view'); -var SelectView = require('ampersand-select-view'); -var EditStoichSpecieView = require('./edit-stoich-specie'); -var EditCustomStoichSpecieView = require('./edit-custom-stoich-specie'); +let View = require('ampersand-view'); +let SelectView = require('ampersand-select-view'); +let EditStoichSpecieView = require('./edit-stoich-specie'); +let EditCustomStoichSpecieView = require('./edit-custom-stoich-specie'); //templates -var template = require('../templates/includes/reactantProduct.pug'); +let template = require('../templates/reactantProduct.pug'); module.exports = View.extend({ template: template, @@ -43,37 +43,41 @@ module.exports = View.extend({ this.fieldTitle = args.fieldTitle; }, render: function () { - var self = this; View.prototype.render.apply(this, arguments); - var args = { + let args = { viewOptions: { name: 'stoich-specie', - label: '', required: true, textAttribute: 'name', eagerValidate: true, - // Set idAttribute to name. Models may not be saved yet so id is unreliable (so is cid). - // Use name since it *should be* unique. idAttribute: 'name', - options: self.species + options: this.species } }; - var type = self.reactionType; - var StoichSpeciesView = (type.startsWith('custom')) ? EditCustomStoichSpecieView : EditStoichSpecieView - self.renderCollection( - self.collection, + let type = this.reactionType; + let StoichSpeciesView = (type.startsWith('custom')) ? EditCustomStoichSpecieView : EditStoichSpecieView; + this.renderCollection( + this.collection, StoichSpeciesView, - self.queryByHook('reactants-editor'), + this.queryByHook('reactants-editor'), args ); if(this.reactionType.startsWith('custom')) { - $(this.queryByHook('collapse')).collapse() + $(this.queryByHook('collapse')).collapse(); } this.toggleAddSpecieButton(); if(this.fieldTitle === "Reactants"){ - $(this.queryByHook('field-title-tooltip')).prop('title', this.parent.parent.tooltips.reactant) + $(this.queryByHook('field-title-tooltip')).prop('title', this.parent.parent.tooltips.reactant); }else{ - $(this.queryByHook('field-title-tooltip')).prop('title', this.parent.parent.tooltips.product) + $(this.queryByHook('field-title-tooltip')).prop('title', this.parent.parent.tooltips.product); + } + }, + addSelectedSpecie: function () { + var specieName = this.specieName ? this.specieName : 'Pick a variable'; + if(this.validateAddSpecie()) { + this.collection.addStoichSpecie(specieName); + this.toggleAddSpecieButton(); + this.collection.parent.trigger('change-reaction'); } }, selectSpecie: function (e) { @@ -85,14 +89,6 @@ module.exports = View.extend({ } this.toggleAddSpecieButton(); }, - addSelectedSpecie: function () { - var specieName = this.specieName ? this.specieName : 'Pick a variable'; - if(this.validateAddSpecie()) { - this.collection.addStoichSpecie(specieName); - this.toggleAddSpecieButton(); - this.collection.parent.trigger('change-reaction') - } - }, toggleAddSpecieButton: function () { if(!this.validateAddSpecie()){ $(this.queryByHook('add-selected-specie')).prop('disabled', true); @@ -103,13 +99,10 @@ module.exports = View.extend({ }, validateAddSpecie: function () { if(this.hasSelectedSpecie){ - if(!this.collection.length) return true; - if(this.collection.length < 2 && this.collection.at(0).ratio < 2) - return true; - if(this.reactionType !== 'custom-massaction') - return true; - if(!this.isReactants) - return true; + if(!this.collection.length) { return true; } + if(this.collection.length < 2 && this.collection.at(0).ratio < 2) { return true; } + if(this.reactionType !== 'custom-massaction') { return true; } + if(!this.isReactants) { return true; } return false; } return false; @@ -120,17 +113,14 @@ module.exports = View.extend({ prepareView: function (el) { return new SelectView({ name: 'stoich-specie', - label: '', required: false, textAttribute: 'name', eagerValidate: false, - // Set idAttribute to name. Models may not be saved yet so id is unreliable (so is cid). - // Use name since it *should be* unique. idAttribute: 'name', options: this.species, - unselectedText: this.unselectedText, + unselectedText: this.unselectedText }); } } - }, + } }); \ No newline at end of file diff --git a/client/views/reaction-details.js b/client/model-view/views/reaction-details.js similarity index 74% rename from client/views/reaction-details.js rename to client/model-view/views/reaction-details.js index 00f27574a7..91dfe74735 100644 --- a/client/views/reaction-details.js +++ b/client/model-view/views/reaction-details.js @@ -16,23 +16,22 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var _ = require('underscore'); -var $ = require('jquery'); -var katex = require('katex'); +let $ = require('jquery'); +let katex = require('katex'); +let _ = require('underscore'); //support files -let app = require('../app'); -//config -var ReactionTypes = require('../reaction-types'); +let app = require('../../app'); +let ReactionTypes = require('../../reaction-types'); //models -var StoichSpecie = require('../models/stoich-specie'); +let StoichSpecie = require('../../models/stoich-specie'); //views -var View = require('ampersand-view'); -var SelectView = require('ampersand-select-view'); -var InputView = require('./input'); -var ReactionTypesView = require('./reaction-types'); -var ReactantProductView = require('./reactant-product'); +let InputView = require('../../views/input'); +let View = require('ampersand-view'); +let SelectView = require('ampersand-select-view'); +let ReactionTypesView = require('./reaction-types'); +let ReactantProductView = require('./reactant-product'); //templates -var template = require('../templates/includes/reactionDetails.pug'); +let template = require('../templates/reactionDetails.pug'); module.exports = View.extend({ template: template, @@ -53,68 +52,51 @@ module.exports = View.extend({ 'model.hasConflict': { type: function (el, value, previousValue) { if(value) { - $(this.queryByHook('conflicting-modes-message')).collapse('show') + $(this.queryByHook('conflicting-modes-message')).collapse('show'); }else{ - $(this.queryByHook('conflicting-modes-message')).collapse('hide') + $(this.queryByHook('conflicting-modes-message')).collapse('hide'); } }, - hook: 'conflicting-modes-message', - }, + hook: 'conflicting-modes-message' + } }, events: { 'change [data-hook=select-rate-parameter]' : 'selectRateParam', - 'change [data-hook=select-reaction-type]' : 'selectReactionType', + 'change [data-hook=select-reaction-type]' : 'selectReactionType' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); - var self = this; + let self = this; this.model.on("change:reaction_type", function (model) { self.updateStoichSpeciesForReactionType(model.reactionType); }); }, render: function () { View.prototype.render.apply(this, arguments); - var self = this; - var reactantsView = new ReactantProductView({ - collection: this.model.reactants, - species: this.model.collection.parent.species, - reactionType: this.model.reactionType, - fieldTitle: 'Reactants', - isReactants: true - }); - var productsView = new ReactantProductView({ - collection: this.model.products, - species: this.model.collection.parent.species, - reactionType: this.model.reactionType, - fieldTitle: 'Products', - isReactants: false - }); - this.renderReactionTypesSelectView() + let self = this; + this.renderReactionTypesSelectView(); if(this.model.reactionType === 'custom-propensity'){ - var propensityView = new InputView({ + let propensityView = new InputView({ parent: this, required: true, name: 'rate', - label: '', - tests:'', modelKey:'propensity', valueType: 'string', value: this.model.propensity, placeholder: "--No Expression Entered--" }); - app.registerRenderSubview(this, propensityView, 'select-rate-parameter') - $(this.queryByHook('rate-parameter-label')).text('Propensity:') + app.registerRenderSubview(this, propensityView, 'select-rate-parameter'); + $(this.queryByHook('rate-parameter-label')).text('Propensity:'); $(this.queryByHook('rate-parameter-tooltip')).prop('title', this.parent.tooltips.propensity); }else{ // make sure the reaction has a rate and that rate exists in the parameters collection let paramIDs = this.model.collection.parent.parameters.map(function (param) { - return param.compID + return param.compID; }); if(!this.model.rate.compID || !paramIDs.includes(this.model.rate.compID)) { - this.model.rate = this.model.collection.getDefaultRate() + this.model.rate = this.model.collection.getDefaultRate(); } - var rateParameterView = new SelectView({ - label: '', + let rateParameterView = new SelectView({ name: 'rate', required: true, idAttribute: 'cid', @@ -123,135 +105,135 @@ module.exports = View.extend({ options: this.model.collection.parent.parameters, // For new reactions (with no rate.name) just use the first parameter in the Parameters collection // Else fetch the right Parameter from Parameters based on existing rate - value: this.model.rate.name ? this.getRateFromParameters(this.model.rate.name) : this.model.collection.parent.parameters.at(0), + value: this.model.rate.name ? this.getRateFromParameters(this.model.rate.name) : this.model.collection.parent.parameters.at(0) }); app.registerRenderSubview(this, rateParameterView, 'select-rate-parameter'); - $(this.queryByHook('rate-parameter-label')).text('Rate Parameter:') + $(this.queryByHook('rate-parameter-label')).text('Rate Parameter:'); $(this.queryByHook('rate-parameter-tooltip')).prop('title', this.parent.tooltips.rate); } + let reactantsView = new ReactantProductView({ + collection: this.model.reactants, + species: this.model.collection.parent.species, + reactionType: this.model.reactionType, + fieldTitle: 'Reactants', + isReactants: true + }); + app.registerRenderSubview(this, reactantsView, 'reactants-editor'); + let productsView = new ReactantProductView({ + collection: this.model.products, + species: this.model.collection.parent.species, + reactionType: this.model.reactionType, + fieldTitle: 'Products', + isReactants: false + }); + app.registerRenderSubview(this, productsView, 'products-editor'); if(this.model.collection.parent.is_spatial) { - var typesView = new ReactionTypesView({ + let typesView = new ReactionTypesView({ model: this.model, parent: this }); app.registerRenderSubview(this, typesView, 'domain-types-editor'); } - app.registerRenderSubview(this, reactantsView, 'reactants-editor'); - app.registerRenderSubview(this, productsView, 'products-editor'); this.totalRatio = this.getTotalReactantRatio(); - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); - }); + app.tooltipSetup(); this.toggleCustomReactionError(); }, - update: function () { + getArrayOfDefaultStoichSpecies: function (arr) { + return arr.map(function (params) { + let stoichSpecie = new StoichSpecie(params); + stoichSpecie.specie = this.parent.getDefaultSpecie(); + return stoichSpecie; + }, this); + }, + getRateFromParameters: function (name) { + // Seems like model.rate is not actually part of the Parameters collection + // Get the Parameter from Parameters that matches model.rate + // TODO this is some garbagio, get model.rate into Parameters collection...? + if (!name) { name = this.model.rate.name }; + let rate = this.model.collection.parent.parameters.filter(function (param) { + return param.name === name; + })[0]; + return rate; + }, + getReactionTypeLabels: function () { + return _.map(ReactionTypes, function (val, key) { return val.label; }); }, - updateValid: function () { + getTotalReactantRatio: function () { + return this.model.reactants.length; + }, + renderReactionTypes: function () { + if(this.model.collection.parent.parameters.length < 1){ return }; + let options = { + displayMode: true, + output: 'html' + } + katex.render(ReactionTypes['creation'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['0'], options); + katex.render(ReactionTypes['destruction'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['1'], options); + katex.render(ReactionTypes['change'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['2'], options); + katex.render(ReactionTypes['dimerization'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['3'], options); + katex.render(ReactionTypes['merge'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['4'], options); + katex.render(ReactionTypes['split'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['5'], options); + katex.render(ReactionTypes['four'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['6'], options); }, renderReactionTypesSelectView: function () { if(this.reactionTypesSelectView) { - this.reactionTypesSelectView.remove() + this.reactionTypesSelectView.remove(); } - - var options = []; if(this.model.collection.parent.parameters.length <= 0){ - options = ["Custom propensity"]; + var options = ["Custom propensity"]; } else{ - options = this.getReactionTypeLabels(); + var options = this.getReactionTypeLabels(); } - this.reactionTypesSelectView = new SelectView({ label: 'Reaction Type:', name: 'reaction-type', required: true, idAttribute: 'cid', options: options, - value: ReactionTypes[this.model.reactionType].label, + value: ReactionTypes[this.model.reactionType].label }); - app.registerRenderSubview(this, this.reactionTypesSelectView, 'select-reaction-type'); this.renderReactionTypes(); }, selectRateParam: function (e) { if(this.model.reactionType !== 'custom-propensity') { - var val = e.target.selectedOptions.item(0).text; - var param = this.getRateFromParameters(val); + let val = e.target.selectedOptions.item(0).text; + let param = this.getRateFromParameters(val); this.model.rate = param || this.model.rate; this.model.trigger("change"); this.model.collection.trigger("change"); } }, - getRateFromParameters: function (name) { - // Seems like model.rate is not actually part of the Parameters collection - // Get the Parameter from Parameters that matches model.rate - // TODO this is some garbagio, get model.rate into Parameters collection...? - if (!name) { name = this.model.rate.name } - var rate = this.model.collection.parent.parameters.filter(function (param) { - return param.name === name; - })[0]; - return rate - }, selectReactionType: function (e) { - var label = e.target.selectedOptions.item(0).value; - var type = _.findKey(ReactionTypes, function (o) { return o.label === label; }); + let label = e.target.selectedOptions.item(0).value; + let type = _.findKey(ReactionTypes, function (o) { return o.label === label; }); this.model.reactionType = type; - this.model.summary = label + this.model.summary = label; this.updateStoichSpeciesForReactionType(type); this.model.collection.trigger("change"); - this.model.trigger('change-reaction') + this.model.trigger('change-reaction'); this.render(); }, - updateStoichSpeciesForReactionType: function (type) { - var args = this.parent.getStoichArgsForReactionType(type); - var newReactants = this.getArrayOfDefaultStoichSpecies(args.reactants); - var newProducts = this.getArrayOfDefaultStoichSpecies(args.products); - this.model.reactants.reset(newReactants); - this.model.products.reset(newProducts); - if(type !== 'custom-propensity') - this.model.rate = this.model.collection.getDefaultRate(); - }, - getArrayOfDefaultStoichSpecies: function (arr) { - return arr.map(function (params) { - var stoichSpecie = new StoichSpecie(params); - stoichSpecie.specie = this.parent.getDefaultSpecie(); - return stoichSpecie; - }, this); - }, - getReactionTypeLabels: function () { - return _.map(ReactionTypes, function (val, key) { return val.label; }) - }, - getTotalReactantRatio: function () { - return this.model.reactants.length; - }, toggleCustomReactionError: function () { - let errorMsg = $(this.queryByHook("custom-reaction-error")) + let errorMsg = $(this.queryByHook("custom-reaction-error")); if(this.model.reactants.length <= 0 && this.model.products.length <= 0) { - errorMsg.addClass('component-invalid') - errorMsg.removeClass('component-valid') + errorMsg.addClass('component-invalid'); + errorMsg.removeClass('component-valid'); }else{ - errorMsg.addClass('component-valid') - errorMsg.removeClass('component-invalid') + errorMsg.addClass('component-valid'); + errorMsg.removeClass('component-invalid'); } }, - renderReactionTypes: function () { - if(this.model.collection.parent.parameters.length < 1){ - return - } - var options = { - displayMode: true, - output: 'html' - } - katex.render(ReactionTypes['creation'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['0'], options); - katex.render(ReactionTypes['destruction'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['1'], options); - katex.render(ReactionTypes['change'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['2'], options); - katex.render(ReactionTypes['dimerization'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['3'], options); - katex.render(ReactionTypes['merge'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['4'], options); - katex.render(ReactionTypes['split'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['5'], options); - katex.render(ReactionTypes['four'].label, this.queryByHook('select-reaction-type').firstChild.children[1]['6'], options); + update: function () {}, + updateStoichSpeciesForReactionType: function (type) { + let args = this.parent.getStoichArgsForReactionType(type); + let newReactants = this.getArrayOfDefaultStoichSpecies(args.reactants); + let newProducts = this.getArrayOfDefaultStoichSpecies(args.products); + this.model.reactants.reset(newReactants); + this.model.products.reset(newProducts); + if(type !== 'custom-propensity') + this.model.rate = this.model.collection.getDefaultRate(); }, + updateValid: function () {} }); \ No newline at end of file diff --git a/client/views/reaction-listing.js b/client/model-view/views/reaction-listing.js similarity index 80% rename from client/views/reaction-listing.js rename to client/model-view/views/reaction-listing.js index 2503be8ee3..2493684a78 100644 --- a/client/views/reaction-listing.js +++ b/client/model-view/views/reaction-listing.js @@ -16,18 +16,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); -var katex = require('katex'); +let $ = require('jquery'); +let katex = require('katex'); let _ = require('underscore'); //support files -var tests = require('./tests'); -var modals = require('../modals'); +let app = require('../../app'); +let tests = require('../../views/tests'); +let modals = require('../../modals'); //views -var View = require('ampersand-view'); -var InputView = require('./input'); +let InputView = require('../../views/input'); +let View = require('ampersand-view'); //templates -var editTemplate = require('../templates/includes/reactionListing.pug'); -let viewTemplate = require('../templates/includes/viewReactions.pug'); +let viewTemplate = require('../templates/viewReaction.pug'); +let editTemplate = require('../templates/reactionListing.pug'); module.exports = View.extend({ bindings: { @@ -40,10 +41,10 @@ module.exports = View.extend({ katex.render(this.model.summary, this.queryByHook('summary'), { displayMode: true, output: 'html', - maxSize: 5, + maxSize: 5 }); }, - hook: 'summary', + hook: 'summary' }, 'model.selected' : { type: function (el, value, previousValue) { @@ -67,7 +68,7 @@ module.exports = View.extend({ if(this.model.types) { this.model.types.forEach(function (index) { let type = self.model.collection.parent.domain.types.get(index, "typeID"); - self.types.push(type.name) + self.types.push(type.name); }); } }else{ @@ -77,34 +78,18 @@ module.exports = View.extend({ render: function () { this.template = this.viewMode ? viewTemplate : editTemplate; View.prototype.render.apply(this, arguments); - $(document).on('shown.bs.modal', function (e) { - $('[autofocus]', e.target).focus(); - }); - $(document).on('hide.bs.modal', '.modal', function (e) { - e.target.remove() - }); + app.documentSetup(); if(!this.model.annotation){ - $(this.queryByHook('edit-annotation-btn')).text('Add') + $(this.queryByHook('edit-annotation-btn')).text('Add'); } }, - update: function () { - }, - updateValid: function () { - }, - selectReaction: function (e) { - this.model.collection.trigger("select", this.model); - }, - removeReaction: function (e) { - this.collection.removeReaction(this.model); - this.parent.collection.trigger("change"); - }, editAnnotation: function () { - var self = this; - var name = this.model.name; - var annotation = this.model.annotation; if(document.querySelector('#reactionAnnotationModal')) { document.querySelector('#reactionAnnotationModal').remove(); } + let self = this; + let name = this.model.name; + let annotation = this.model.annotation; let modal = $(modals.annotationModalHtml("reaction", name, annotation)).modal(); let okBtn = document.querySelector('#reactionAnnotationModal .ok-model-btn'); let input = document.querySelector('#reactionAnnotationModal #reactionAnnotationInput'); @@ -120,6 +105,15 @@ module.exports = View.extend({ modal.modal('hide'); }); }, + removeReaction: function (e) { + this.collection.removeReaction(this.model); + this.parent.collection.trigger("change"); + }, + selectReaction: function (e) { + this.model.collection.trigger("select", this.model); + }, + update: function () {}, + updateValid: function () {}, updateViewer: function () { this.parent.renderViewReactionView(); }, @@ -131,13 +125,12 @@ module.exports = View.extend({ parent: this, required: true, name: 'name', - label: '', tests: tests.nameTests, modelKey: 'name', valueType: 'string', - value: this.model.name, + value: this.model.name }); - }, - }, - }, + } + } + } }); \ No newline at end of file diff --git a/client/views/reaction-types.js b/client/model-view/views/reaction-types.js similarity index 90% rename from client/views/reaction-types.js rename to client/model-view/views/reaction-types.js index e57eddcc06..9bf2fc4e07 100644 --- a/client/views/reaction-types.js +++ b/client/model-view/views/reaction-types.js @@ -17,10 +17,10 @@ along with this program. If not, see . */ //views -var View = require('ampersand-view'); -var TypesView = require('./component-types'); +let View = require('ampersand-view'); +let TypesView = require('./component-types'); //templates -var template = require('../templates/includes/reactionTypes.pug'); +let template = require('../templates/reactionTypes.pug'); module.exports = View.extend({ template: template, diff --git a/client/views/reactions-editor.js b/client/model-view/views/reactions-view.js similarity index 78% rename from client/views/reactions-editor.js rename to client/model-view/views/reactions-view.js index e6539a856e..912745f565 100644 --- a/client/views/reactions-editor.js +++ b/client/model-view/views/reactions-view.js @@ -16,22 +16,22 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var ViewSwitcher = require('ampersand-view-switcher'); -var katex = require('katex'); -var _ = require('underscore'); -var $ = require('jquery'); +let $ = require('jquery'); +let katex = require('katex'); +let _ = require('underscore'); //support files -let app = require('../app'); -var ReactionTypes = require('../reaction-types'); -var Tooltips = require('../tooltips'); +let app = require('../../app'); +let Tooltips = require('../../tooltips'); +let ReactionTypes = require('../../reaction-types'); //models -var StoichSpeciesCollection = require('../models/stoich-species'); +let StoichSpeciesCollection = require('../../models/stoich-species'); //views -var View = require('ampersand-view'); -var ReactionListingView = require('./reaction-listing'); -var ReactionDetailsView = require('./reaction-details'); +let View = require('ampersand-view'); +let ViewSwitcher = require('ampersand-view-switcher'); +let ReactionListingView = require('./reaction-listing'); +let ReactionDetailsView = require('./reaction-details'); //templates -var template = require('../templates/includes/reactionsEditor.pug'); +let template = require('../templates/reactionsView.pug'); module.exports = View.extend({ template: template, @@ -49,7 +49,7 @@ module.exports = View.extend({ }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); - this.tooltips = Tooltips.reactionsEditor + this.tooltips = Tooltips.reactionsEditor; this.readOnly = attrs.readOnly ? attrs.readOnly : false; if(!this.readOnly) { this.collection.on("select", function (reaction) { @@ -59,23 +59,24 @@ module.exports = View.extend({ this.collection.on("remove", function (reaction) { // Select the last reaction by default // But only if there are other reactions other than the one we're removing - if (reaction.detailsView) + if (reaction.detailsView){ reaction.detailsView.remove(); + } this.collection.removeReaction(reaction); if (this.collection.length) { - var selected = this.collection.at(this.collection.length-1); + let selected = this.collection.at(this.collection.length-1); this.collection.trigger("select", selected); } }, this); this.collection.parent.species.on('add remove', this.toggleAddReactionButton, this); this.collection.parent.parameters.on('add remove', this.toggleReactionTypes, this); - this.collection.parent.on('change', this.toggleProcessError, this) + this.collection.parent.on('change', this.toggleProcessError, this); } }, render: function () { View.prototype.render.apply(this, arguments); if(this.readOnly) { - this.renderViewReactionView() + this.renderViewReactionView(); $(this.queryByHook('reactions-edit-tab')).addClass("disabled"); $(".nav .disabled>a").on("click", function(e) { e.preventDefault(); @@ -86,20 +87,14 @@ module.exports = View.extend({ $(this.queryByHook('view-reactions')).addClass('active'); }else{ this.renderReactionListingViews(); - this.detailsContainer = this.queryByHook('reaction-details-container'); - this.detailsViewSwitcher = new ViewSwitcher({ - el: this.detailsContainer, - }); if (this.collection.length) { this.setSelectedReaction(this.collection.at(0)); this.collection.trigger("select", this.selectedReaction); } - this.collection.trigger("change"); this.toggleAddReactionButton(); if(this.collection.parent.parameters.length > 0){ $(this.queryByHook('add-reaction-partial')).prop('hidden', true); - } - else{ + }else { $(this.queryByHook('add-reaction-full')).prop('hidden', true); } this.renderReactionTypes(); @@ -107,17 +102,47 @@ module.exports = View.extend({ displayMode: false, output: 'html', }); - this.toggleProcessError() + this.toggleProcessError(); $(this.queryByHook('massaction-message')).prop('hidden', this.collection.parent.parameters.length > 0); } }, - update: function () { + changeCollapseButtonText: function (e) { + app.changeCollapseButtonText(this, e); }, - updateValid: function () { + getAnnotation: function (type) { + return ReactionTypes[type].label; }, - renderReactionListingViews: function () { - this.renderEditReactionListingView(); - this.renderViewReactionView(); + getDefaultSpecie: function () { + return this.collection.parent.species.models[0]; + }, + getStoichArgsForReactionType: function(type) { + return ReactionTypes[type]; + }, + handleAddReactionClick: function (e) { + let reactionType = e.delegateTarget.dataset.hook; + let stoichArgs = this.getStoichArgsForReactionType(reactionType); + if(this.parent.model.domain.types) { + var types = this.parent.model.domain.types.map(function (type) { + return type.typeID; + }); + types.shift(); + }else{ + var types = []; + } + let reaction = this.collection.addReaction(reactionType, stoichArgs, types); + reaction.detailsView = this.newDetailsView(reaction); + this.collection.trigger("select", reaction); + app.tooltipSetup(); + }, + newDetailsView: function (reaction) { + let detailsView = new ReactionDetailsView({ model: reaction }); + detailsView.parent = this; + return detailsView; + }, + openReactionsContainer: function () { + $(this.queryByHook('reactions-list-container')).collapse('show'); + let collapseBtn = $(this.queryByHook('collapse')); + collapseBtn.trigger('click'); }, renderEditReactionListingView: function () { if(this.editReactionListingView){ @@ -126,7 +151,7 @@ module.exports = View.extend({ if(this.collection.parent.parameters.length <= 0) { for(var i = 0; i < this.collection.length; i++) { if(this.collection.models[i].reactionType !== "custom-propensity"){ - this.collection.models[i].reactionType = "custom-propensity" + this.collection.models[i].reactionType = "custom-propensity"; } } } @@ -135,12 +160,24 @@ module.exports = View.extend({ ReactionListingView, this.queryByHook('edit-reaction-list') ); - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); + }, + renderReactionListingViews: function () { + this.renderEditReactionListingView(); + this.renderViewReactionView(); + }, + renderReactionTypes: function () { + let options = { + displayMode: false, + output: 'html' + } + katex.render(ReactionTypes['creation'].label, this.queryByHook('creation-lb1'), options); + katex.render(ReactionTypes['destruction'].label, this.queryByHook('destruction-lb1'), options); + katex.render(ReactionTypes['change'].label, this.queryByHook('change-lb1'), options); + katex.render(ReactionTypes['dimerization'].label, this.queryByHook('dimerization-lb1'), options); + katex.render(ReactionTypes['merge'].label, this.queryByHook('merge-lb1'), options); + katex.render(ReactionTypes['split'].label, this.queryByHook('split-lb1'), options); + katex.render(ReactionTypes['four'].label, this.queryByHook('four-lb1'), options); }, renderViewReactionView: function () { if(this.viewReactionListingView){ @@ -163,10 +200,31 @@ module.exports = View.extend({ options ); }, + setDetailsView: function (reaction) { + reaction.detailsView = this.newDetailsView(reaction); + this.detailsViewSwitcher.set(reaction.detailsView); + }, + setSelectedReaction: function (reaction) { + this.collection.each(function (m) { m.selected = false; }); + reaction.selected = true; + this.selectedReaction = reaction; + }, toggleAddReactionButton: function () { $(this.queryByHook('add-reaction-full')).prop('disabled', (this.collection.parent.species.length <= 0)); $(this.queryByHook('add-reaction-partial')).prop('disabled', (this.collection.parent.species.length <= 0)); }, + toggleProcessError: function () { + let model = this.collection.parent; + if(model.is_spatial) {return}; + let errorMsg = $(this.queryByHook('process-component-error')); + if(this.collection.length <= 0 && model.eventsCollection.length <= 0 && model.rules.length <= 0) { + errorMsg.addClass('component-invalid'); + errorMsg.removeClass('component-valid'); + }else{ + errorMsg.addClass('component-valid'); + errorMsg.removeClass('component-invalid'); + } + }, toggleReactionTypes: function (e, prev, curr) { if(curr && curr.add && this.collection.parent.parameters.length === 1){ $(this.queryByHook('massaction-message')).prop('hidden', true); @@ -178,87 +236,19 @@ module.exports = View.extend({ $(this.queryByHook('add-reaction-partial')).prop('hidden', false); } if(this.selectedReaction){ - this.selectedReaction.detailsView.renderReactionTypesSelectView() - } - }, - setSelectedReaction: function (reaction) { - this.collection.each(function (m) { m.selected = false; }); - reaction.selected = true; - this.selectedReaction = reaction; - }, - setDetailsView: function (reaction) { - reaction.detailsView = this.newDetailsView(reaction); - this.detailsViewSwitcher.set(reaction.detailsView); - }, - handleAddReactionClick: function (e) { - var reactionType = e.delegateTarget.dataset.hook; - var stoichArgs = this.getStoichArgsForReactionType(reactionType); - if(this.parent.model.domain.types) { - var types = this.parent.model.domain.types.map(function (type) { - return type.typeID; - }); - types.shift() - }else{ - var types = [] + this.selectedReaction.detailsView.renderReactionTypesSelectView(); } - var reaction = this.collection.addReaction(reactionType, stoichArgs, types); - reaction.detailsView = this.newDetailsView(reaction); - this.collection.trigger("select", reaction); - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); - }); }, - getStoichArgsForReactionType: function(type) { - var args = ReactionTypes[type]; - return args; - }, - newDetailsView: function (reaction) { - var detailsView = new ReactionDetailsView({ model: reaction }); - detailsView.parent = this; - return detailsView - }, - openReactionsContainer: function () { - $(this.queryByHook('reactions-list-container')).collapse('show'); - let collapseBtn = $(this.queryByHook('collapse')) - collapseBtn.trigger('click') - }, - changeCollapseButtonText: function (e) { - app.changeCollapseButtonText(this, e); - }, - getDefaultSpecie: function () { - var value = this.collection.parent.species.models[0]; - return value; - }, - getAnnotation: function (type) { - return ReactionTypes[type].label - }, - toggleProcessError: function () { - let model = this.collection.parent - if(model.is_spatial) {return}; - let errorMsg = $(this.queryByHook('process-component-error')) - if(this.collection.length <= 0 && model.eventsCollection.length <= 0 && model.rules.length <= 0) { - errorMsg.addClass('component-invalid') - errorMsg.removeClass('component-valid') - }else{ - errorMsg.addClass('component-valid') - errorMsg.removeClass('component-invalid') - } - }, - renderReactionTypes: function () { - var options = { - displayMode: false, - output: 'html', + update: function () {}, + updateValid: function () {}, + subviews: { + detailsViewSwitcher: { + hook: "reaction-details-container", + prepareView: function (el) { + return new ViewSwitcher({ + el: el + }); + } } - katex.render(ReactionTypes['creation'].label, this.queryByHook('creation-lb1'), options); - katex.render(ReactionTypes['destruction'].label, this.queryByHook('destruction-lb1'), options); - katex.render(ReactionTypes['change'].label, this.queryByHook('change-lb1'), options); - katex.render(ReactionTypes['dimerization'].label, this.queryByHook('dimerization-lb1'), options); - katex.render(ReactionTypes['merge'].label, this.queryByHook('merge-lb1'), options); - katex.render(ReactionTypes['split'].label, this.queryByHook('split-lb1'), options); - katex.render(ReactionTypes['four'].label, this.queryByHook('four-lb1'), options); } }); \ No newline at end of file diff --git a/client/views/edit-rule.js b/client/model-view/views/rule-view.js similarity index 72% rename from client/views/edit-rule.js rename to client/model-view/views/rule-view.js index 66e36128b8..40b755826a 100644 --- a/client/views/edit-rule.js +++ b/client/model-view/views/rule-view.js @@ -16,26 +16,26 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); let _ = require('underscore'); //support files -let app = require('../app'); -var tests = require('./tests'); -var modals = require('../modals'); +let app = require('../../app'); +let tests = require('../../views/tests'); +let modals = require('../../modals'); //views -var View = require('ampersand-view'); -var InputView = require('./input'); -var SelectView = require('ampersand-select-view'); +let InputView = require('../../views/input'); +let View = require('ampersand-view'); +let SelectView = require('ampersand-select-view'); //templates -var editTemplate = require('../templates/includes/editRule.pug'); -let viewTemplate = require('../templates/includes/viewRules.pug'); +let editTemplate = require('../templates/editRule.pug'); +let viewTemplate = require('../templates/viewRule.pug'); module.exports = View.extend({ events: { 'change [data-hook=rule-type]' : 'selectRuleType', 'change [data-hook=rule-variable]' : 'selectRuleVariable', 'click [data-hook=edit-annotation-btn]' : 'editAnnotation', - 'click [data-hook=remove]' : 'removeRule', + 'click [data-hook=remove]' : 'removeRule' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); @@ -45,29 +45,20 @@ module.exports = View.extend({ this.template = this.viewMode ? viewTemplate : editTemplate; View.prototype.render.apply(this, arguments); if(!this.viewMode){ - this.model.on('change', _.bind(this.updateViewer, this)) + this.model.on('change', _.bind(this.updateViewer, this)); } - $(document).on('shown.bs.modal', function (e) { - $('[autofocus]', e.target).focus(); - }); - $(document).on('hide.bs.modal', '.modal', function (e) { - e.target.remove() - }); + app.documentSetup(); if(!this.model.annotation){ - $(this.queryByHook('edit-annotation-btn')).text('Add') + $(this.queryByHook('edit-annotation-btn')).text('Add'); } }, - update: function (e) { - }, - updateValid: function () { - }, editAnnotation: function () { - var self = this; - var name = this.model.name; - var annotation = this.model.annotation; if(document.querySelector('#ruleAnnotationModal')) { document.querySelector('#ruleAnnotationModal').remove(); } + let self = this; + let name = this.model.name; + let annotation = this.model.annotation; let modal = $(modals.annotationModalHtml("rule", name, annotation)).modal(); let okBtn = document.querySelector('#ruleAnnotationModal .ok-model-btn'); let input = document.querySelector('#ruleAnnotationModal #ruleAnnotationInput'); @@ -84,26 +75,29 @@ module.exports = View.extend({ }); }, getOptions: function () { - var species = this.model.collection.parent.species; - var parameters = this.model.collection.parent.parameters; - var specs = species.map(function (specie) { + let species = this.model.collection.parent.species; + let parameters = this.model.collection.parent.parameters; + let specs = species.map(function (specie) { return [specie.compID, specie.name]; }); - var params = parameters.map(function (parameter) { + let params = parameters.map(function (parameter) { return [parameter.compID, parameter.name]; }); - let options = [{groupName: "Variables", options: specs}, - {groupName: "Parameters", options: params}]; + let options = [{groupName: Boolean(specs) ? "Variables" : "Variables (empty)", options: specs}, + {groupName: Boolean(params) ? "Parameters" : "Parameters (empty)", options: params}]; return options; }, + removeRule: function () { + this.model.collection.removeRule(this.model); + }, selectRuleType: function (e) { this.model.type = e.target.value; }, selectRuleVariable: function (e) { - var species = this.model.collection.parent.species; - var parameters = this.model.collection.parent.parameters; - var compID = Number(e.target.value); - var ruleVar = species.filter(function (specie) { + let species = this.model.collection.parent.species; + let parameters = this.model.collection.parent.parameters; + let compID = Number(e.target.value); + let ruleVar = species.filter(function (specie) { if(specie.compID === compID) { return specie; } @@ -117,9 +111,8 @@ module.exports = View.extend({ } this.model.variable = ruleVar[0]; }, - removeRule: function () { - this.model.collection.removeRule(this.model); - }, + update: function (e) {}, + updateValid: function () {}, updateViewer: function () { this.parent.renderViewRules(); }, @@ -131,11 +124,10 @@ module.exports = View.extend({ parent: this, required: true, name: 'rule-name', - label: '', tests: tests.nameTests, modelKey: 'name', valueType: 'string', - value: this.model.name, + value: this.model.name }); } }, @@ -148,7 +140,7 @@ module.exports = View.extend({ required: true, idAttributes: 'cid', options: options, - value: this.model.type, + value: this.model.type }); } }, @@ -161,7 +153,7 @@ module.exports = View.extend({ required: true, idAttributes: 'cid', groupOptions: options, - value: this.model.variable.compID, + value: this.model.variable.compID }); } }, diff --git a/client/views/rules-editor.js b/client/model-view/views/rules-view.js similarity index 71% rename from client/views/rules-editor.js rename to client/model-view/views/rules-view.js index 489a41e770..8b82069cc7 100644 --- a/client/views/rules-editor.js +++ b/client/model-view/views/rules-view.js @@ -16,29 +16,29 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); //support files -let app = require('../app'); -var Tooltips = require('../tooltips'); +let app = require('../../app'); +let Tooltips = require('../../tooltips'); //views -var View = require('ampersand-view'); -var RuleView = require('./edit-rule'); +let View = require('ampersand-view'); +let RuleView = require('./rule-view'); //templates -var template = require('../templates/includes/ruleEditor.pug'); +let template = require('../templates/rulesView.pug'); module.exports = View.extend({ template: template, events: { 'click [data-hook=rate-rule]' : 'addRule', 'click [data-hook=assignment-rule]' : 'addRule', - 'click [data-hook=collapse]' : 'changeCollapseButtonText', + 'click [data-hook=collapse]' : 'changeCollapseButtonText' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); this.readOnly = attrs.readOnly ? attrs.readOnly : false; this.collection.parent.species.on('add remove', this.toggleAddRuleButton, this); this.collection.parent.parameters.on('add remove', this.toggleAddRuleButton, this); - this.tooltips = Tooltips.rulesEditor + this.tooltips = Tooltips.rulesEditor; }, render: function () { View.prototype.render.apply(this, arguments); @@ -57,9 +57,13 @@ module.exports = View.extend({ } this.renderViewRules(); }, - update: function () { + addRule: function (e) { + let type = e.target.dataset.name; + this.collection.addRule(type); + app.tooltipSetup(); }, - updateValid: function () { + changeCollapseButtonText: function (e) { + app.changeCollapseButtonText(this, e); }, renderEditRules: function () { if(this.rulesView) { @@ -70,12 +74,7 @@ module.exports = View.extend({ RuleView, this.queryByHook('edit-rule-list-container') ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); }, renderViewRules: function () { if(this.viewRulesView) { @@ -94,32 +93,15 @@ module.exports = View.extend({ this.queryByHook('view-rules-list-container'), options ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); }, toggleAddRuleButton: function () { this.renderEditRules(); - var numSpecies = this.collection.parent.species.length; - var numParameters = this.collection.parent.parameters.length; - var disabled = numSpecies <= 0 && numParameters <= 0 + let numSpecies = this.collection.parent.species.length; + let numParameters = this.collection.parent.parameters.length; + let disabled = numSpecies <= 0 && numParameters <= 0; $(this.queryByHook('add-rule')).prop('disabled', disabled); }, - addRule: function (e) { - var type = e.target.dataset.name - this.collection.addRule(type); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); - }); - }, - changeCollapseButtonText: function (e) { - app.changeCollapseButtonText(this, e); - }, + update: function () {}, + updateValid: function () {} }); \ No newline at end of file diff --git a/client/views/sbml-component-editor.js b/client/model-view/views/sbml-components-view.js similarity index 82% rename from client/views/sbml-component-editor.js rename to client/model-view/views/sbml-components-view.js index 678984682d..a7257a35c5 100644 --- a/client/views/sbml-component-editor.js +++ b/client/model-view/views/sbml-components-view.js @@ -16,15 +16,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -var $ = require('jquery'); +let $ = require('jquery'); //support files -let app = require('../app'); -var Tooltips = require('../tooltips'); +let app = require('../../app'); +let Tooltips = require('../../tooltips'); //views -var View = require('ampersand-view'); -var EditFunctionDefinition = require('./edit-function-definition'); +let View = require('ampersand-view'); +let EditFunctionDefinition = require('./function-definition-view'); //templates -var template = require('../templates/includes/sbmlComponentEditor.pug'); +let template = require('../templates/sbmlComponentsView.pug'); module.exports = View.extend({ template: template, @@ -54,6 +54,9 @@ module.exports = View.extend({ } this.renderViewFunctionDefinitionView(); }, + changeCollapseButtonText: function (e) { + app.changeCollapseButtonText(this, e); + }, renderEditFunctionDefinitionView: function () { if(this.editFunctionDefinitionView){ this.editFunctionDefinitionView.remove(); @@ -63,12 +66,7 @@ module.exports = View.extend({ EditFunctionDefinition, this.queryByHook('edit-function-definition-list') ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); + app.tooltipSetup(); }, renderViewFunctionDefinitionView: function () { if(this.viewFunctionDefinitionView) { @@ -87,14 +85,6 @@ module.exports = View.extend({ this.queryByHook('view-function-definition-list'), options ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); - }, - changeCollapseButtonText: function (e) { - app.changeCollapseButtonText(this, e); - }, + app.tooltipSetup(); + } }); \ No newline at end of file diff --git a/client/views/edit-species.js b/client/model-view/views/specie-view.js similarity index 91% rename from client/views/edit-species.js rename to client/model-view/views/specie-view.js index 39a7e6f744..633890e2f6 100644 --- a/client/views/edit-species.js +++ b/client/model-view/views/specie-view.js @@ -19,19 +19,19 @@ along with this program. If not, see . let $ = require('jquery'); let _ = require('underscore'); //support files -let app = require('../app'); -let tests = require('./tests'); -let modals = require('../modals'); +let app = require('../../app'); +let tests = require('../../views/tests'); +let modals = require('../../modals'); //views -let InputView = require('./input'); +let InputView = require('../../views/input'); let View = require('ampersand-view'); let TypesView = require('./component-types'); let SelectView = require('ampersand-select-view'); //templates -let editTemplate = require('../templates/includes/editSpecies.pug'); -let editSpatialTemplate = require('../templates/includes/editSpatialSpecies.pug'); -let viewTemplate = require('../templates/includes/viewSpecies.pug'); -let viewSpatialTemplate = require('../templates/includes/viewSpatialSpecies.pug'); +let editTemplate = require('../templates/editSpecie.pug'); +let editSpatialTemplate = require('../templates/editSpatialSpecie.pug'); +let viewTemplate = require('../templates/viewSpecie.pug'); +let viewSpatialTemplate = require('../templates/viewSpatialSpecie.pug'); module.exports = View.extend({ bindings: { @@ -196,38 +196,38 @@ module.exports = View.extend({ if(this.viewMode || this.parent.spatial) {return} // Update validation requirements and re-run tests for inputSwitchTol. // This removes error reporting not using switching tolerance - let shouldValidateTol = this.model.mode === "dynamic" && this.model.isSwitchTol + let shouldValidateTol = this.model.mode === "dynamic" && this.model.isSwitchTol; this.inputSwitchTol.required = shouldValidateTol; - this.inputSwitchTol.tests = shouldValidateTol ? tests.valueTests : [] - this.inputSwitchTol.runTests() + this.inputSwitchTol.tests = shouldValidateTol ? tests.valueTests : []; + this.inputSwitchTol.runTests(); // Update validation requirements and re-run tests for inputSwitchMin. // This removes error reporting when not using minimum value for switching. - let shouldValidateMin = this.model.mode === "dynamic" && !this.model.isSwitchTol + let shouldValidateMin = this.model.mode === "dynamic" && !this.model.isSwitchTol; this.inputSwitchMin.required = shouldValidateMin; - this.inputSwitchMin.tests = shouldValidateMin ? tests.valueTests : [] - this.inputSwitchMin.runTests() + this.inputSwitchMin.tests = shouldValidateMin ? tests.valueTests : []; + this.inputSwitchMin.runTests(); // Add/Remove 'input-invalid' class from inputSwitchTol and inputSwitchMin based on whether // the user is using switching tolerance or minimum value for switching - let tolInput = $(this.queryByHook('switching-tolerance')).find('input')[0] - let minInput = $(this.queryByHook('switching-threshold')).find('input')[0] + let tolInput = $(this.queryByHook('switching-tolerance')).find('input')[0]; + let minInput = $(this.queryByHook('switching-threshold')).find('input')[0]; if(this.model.mode !== "dynamic") { - $(tolInput).removeClass('input-invalid') - $(minInput).removeClass('input-invalid') + $(tolInput).removeClass('input-invalid'); + $(minInput).removeClass('input-invalid'); }else if(this.model.isSwitchTol){ - $(minInput).removeClass('input-invalid') + $(minInput).removeClass('input-invalid'); if(this.model.switchTol === "" || isNaN(this.model.switchTol)){ - $(tolInput).addClass('input-invalid') + $(tolInput).addClass('input-invalid'); } }else{ - $(tolInput).removeClass('input-invalid') + $(tolInput).removeClass('input-invalid'); if(this.model.switchMin === "" || isNaN(this.model.switchMin)){ - $(minInput).addClass('input-invalid') + $(minInput).addClass('input-invalid'); } } }, updateValid: function (e) {}, updateViewer: function () { - this.parent.renderViewSpeciesView() + this.parent.renderViewSpeciesView(); }, subviews: { inputName: { diff --git a/client/views/species-editor.js b/client/model-view/views/species-view.js similarity index 80% rename from client/views/species-editor.js rename to client/model-view/views/species-view.js index 9ac3ae456e..f9aca59ac9 100644 --- a/client/views/species-editor.js +++ b/client/model-view/views/species-view.js @@ -18,14 +18,14 @@ along with this program. If not, see . let $ = require('jquery'); //support files -let app = require('../app'); -let Tooltips = require('../tooltips'); +let app = require('../../app'); +let Tooltips = require('../../tooltips'); //views let View = require('ampersand-view'); -let SpecieView = require('./edit-species'); +let SpecieView = require('./specie-view'); //templates -let speciesTemplate = require('../templates/includes/speciesEditor.pug'); -let spatialSpeciesTemplate = require('../templates/includes/spatialSpeciesEditor.pug'); +let speciesTemplate = require('../templates/speciesView.pug'); +let spatialSpeciesTemplate = require('../templates/spatialSpeciesView.pug'); module.exports = View.extend({ events: { @@ -34,12 +34,12 @@ module.exports = View.extend({ }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); - this.spatial = attrs.spatial + this.spatial = attrs.spatial; this.readOnly = attrs.readOnly ? attrs.readOnly : false; this.template = this.spatial ? spatialSpeciesTemplate : speciesTemplate; this.tooltips = Tooltips.speciesEditor; this.defaultMode = attrs.defaultMode; - let self = this + let self = this; this.collection.on('update-species', function (compID, specie, isNameUpdate, isDefaultMode) { self.collection.parent.reactions.forEach(function (reaction) { reaction.reactants.forEach(function (reactant) { @@ -55,7 +55,7 @@ module.exports = View.extend({ if(isNameUpdate) { reaction.buildSummary(); if(reaction.selected) { - self.parent.reactionsEditor.setDetailsView(reaction); + self.parent.reactionsView.setDetailsView(reaction); } }else if(!isDefaultMode || specie.compID === self.collection.models[self.collection.length-1].compID){ reaction.checkModes(); @@ -77,7 +77,7 @@ module.exports = View.extend({ } }); if(isNameUpdate) { - self.parent.renderRulesView(); + self.parent.rulesView.renderEditRules(); } }); }, @@ -103,19 +103,13 @@ module.exports = View.extend({ var types = this.parent.model.domain.types.map(function (type) { return type.typeID; }); - types.shift() + types.shift(); }else{ - var types = [] + var types = []; } this.collection.addSpecie(types); - this.toggleSpeciesCollectionError() - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); - }); + this.toggleSpeciesCollectionError(); + app.tooltipSetup(); }, changeCollapseButtonText: function (e) { app.changeCollapseButtonText(this, e); @@ -139,13 +133,7 @@ module.exports = View.extend({ SpecieView, this.queryByHook('edit-specie-list') ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); - }); + app.tooltipSetup(); }, renderViewSpeciesView: function () { if(this.viewSpeciesView){ @@ -169,23 +157,17 @@ module.exports = View.extend({ this.queryByHook('view-specie-list'), options ); - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - - }); - }); + app.tooltipSetup(); }, toggleSpeciesCollectionError: function () { if(this.spatial) {return}; - let errorMsg = $(this.queryByHook('species-collection-error')) + let errorMsg = $(this.queryByHook('species-collection-error')); if(this.collection.length <= 0) { - errorMsg.addClass('component-invalid') - errorMsg.removeClass('component-valid') + errorMsg.addClass('component-invalid'); + errorMsg.removeClass('component-valid'); }else{ - errorMsg.addClass('component-valid') - errorMsg.removeClass('component-invalid') + errorMsg.addClass('component-valid'); + errorMsg.removeClass('component-invalid'); } } }); diff --git a/client/pages/file-browser.js b/client/pages/file-browser.js index 080cc866dd..15d3d04d28 100644 --- a/client/pages/file-browser.js +++ b/client/pages/file-browser.js @@ -898,6 +898,22 @@ let FileBrowser = PageView.extend({ }); }); }, + publishNotebookPresentation: function (o) { + let queryStr = "?path=" + o.original._path; + let endpoint = path.join(app.getApiPath(), "notebook/presentation") + queryStr; + app.getXHR(endpoint, { + success: function (err, response, body) { + let title = body.message; + let linkHeaders = ["Presentation Link", "Download Link", "Open Link"]; + let links = body.links; + let name = o.original._path.split('/').pop().split('.ipynb')[0]; + $(modals.presentationLinks(title, name, linkHeaders, links)).modal(); + }, + error: function (err, response, body) { + $(modals.newProjectModelErrorHtml(body.Reason, body.Message)).modal(); + } + }); + }, setupJstree: function () { var self = this; $.jstree.defaults.contextmenu.items = (o, cb) => { @@ -1314,6 +1330,17 @@ let FileBrowser = PageView.extend({ } } } + let notebook = { + "publish" : { + "label" : "Publish", + "_disabled" : false, + "separator_before" : false, + "separator_after" : false, + "action" : function (data) { + self.publishNotebookPresentation(o); + } + } + } if (o.type === 'root'){ return folder } @@ -1341,7 +1368,13 @@ let FileBrowser = PageView.extend({ if (o.text.endsWith(".zip")) { return $.extend(open, extractAll, common) } - if (o.type === 'notebook' || o.type === "other") { + if (o.type === 'notebook') { + if(app.getBasePath() === "/") { + return $.extend(open, common) + } + return $.extend(open, notebook, common) + } + if (o.type === 'other') { return $.extend(open, common) } if (o.type === 'sbml-model') { diff --git a/client/pages/job-presentation.js b/client/pages/job-presentation.js new file mode 100644 index 0000000000..fe34aeb5f6 --- /dev/null +++ b/client/pages/job-presentation.js @@ -0,0 +1,95 @@ +/* +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +let $ = require('jquery'); +let path = require('path'); +let domReady = require('domready'); +let bootstrap = require('bootstrap'); +//support files +let app = require("../app"); +//models +let Job = require("../models/job"); +//views +let PageView = require('./base'); +let ModelView = require('../views/model-viewer'); +let ResultsView = require('../views/workflow-results'); +let SettingsView = require('../views/settings-viewer'); +//templates +let template = require('../templates/pages/jobPresentation.pug'); + +import bootstrapStyles from '../styles/bootstrap.css'; +import styles from '../styles/styles.css'; +import fontawesomeStyles from '@fortawesome/fontawesome-free/css/svg-with-js.min.css' + +let JobPresentationPage = PageView.extend({ + template: template, + initialize: function () { + PageView.prototype.initialize.apply(this, arguments); + console.log("TODO: get the path to the job from the url") + // let urlParams = new URLSearchParams(window.location.search) + // this.model = new Job({ + // directory: urlParams.get("path") + // }); + console.log("TODO: get job from file system using the app.getXHR function") + // let self = this; + // let queryStr = "?path=" + this.model.directory; + // let endpoint = path.join(); + // app.getXHR(endpoint, { + // success: function (err, response, body) { + // self.model.set(body); + // self.model.type = body.titleType; + // self.renderSubviews(); + // } + // }); + console.log("TODO: generate the open link and store in this.open") + }, + renderSubviews: function () { + PageView.prototype.render.apply(this, arguments); + this.renderResultsContainer(); + this.renderSettingsContainer(); + this.renderModelContainer(); + }, + renderModelContainer: function () { + let modelView = new ModelView({ + model: this.model.model, + mode: "presentation" + }); + app.registerRenderSubview(this, modelView, "job-model"); + }, + renderResultsContainer: function () { + let resultsView = new ResultsView({ + model: this.model, + mode: "presentation" + }); + app.registerRenderSubview(this, resultsView, "job-results"); + }, + renderSettingsContainer: function () { + let settingsView = new SettingsView({ + model: this.model.settings, + mode: "presentation" + }); + app.registerRenderSubview(this, settingsView, "job-settings"); + } +}); + +domReady(() => { + let p = new JobPresentationPage({ + el: document.body + }); + p.render(); +}); \ No newline at end of file diff --git a/client/pages/model-editor.js b/client/pages/model-editor.js index dea04098a6..2c6826b4c0 100644 --- a/client/pages/model-editor.js +++ b/client/pages/model-editor.js @@ -22,24 +22,14 @@ let path = require('path'); //support files var app = require('../app'); var modals = require('../modals'); -var tests = require('../views/tests'); let Tooltips = require("../tooltips"); //views var PageView = require('../pages/base'); -var InputView = require('../views/input'); -var DomainViewer = require('../views/domain-viewer'); -var SpeciesEditorView = require('../views/species-editor'); -var InitialConditionsEditorView = require('../views/initial-conditions-editor'); -var ParametersEditorView = require('../views/parameters-editor'); +let ModelView = require('../model-view/model-view'); var ParticleViewer = require('../views/view-particle'); -var ReactionsEditorView = require('../views/reactions-editor'); -var EventsEditorView = require('../views/events-editor'); -var RulesEditorView = require('../views/rules-editor'); -var SBMLComponentView = require('../views/sbml-component-editor'); var TimespanSettingsView = require('../views/timespan-settings'); var ModelStateButtonsView = require('../views/model-state-buttons'); var QuickviewDomainTypes = require('../views/quickview-domain-types'); -let BoundaryConditionsView = require('../views/boundary-conditions-editor'); //models var Model = require('../models/model'); var Domain = require('../models/domain'); @@ -51,14 +41,9 @@ import initPage from './page.js'; let ModelEditor = PageView.extend({ template: template, events: { - 'change [data-hook=all-continuous]' : 'setDefaultMode', - 'change [data-hook=all-discrete]' : 'setDefaultMode', - 'change [data-hook=advanced]' : 'setDefaultMode', 'click [data-hook=edit-model-help]' : function () { let modal = $(modals.operationInfoModalHtml('model-editor')).modal(); }, - 'change [data-hook=edit-volume]' : 'updateVolumeViewer', - 'click [data-hook=collapse-me-advanced-section]' : 'changeCollapseButtonText', 'click [data-hook=project-breadcrumb-link]' : 'handleProjectBreadcrumbClick', 'click [data-hook=toggle-preview-plot]' : 'togglePreviewPlot', 'click [data-hook=toggle-preview-domain]' : 'toggleDomainPlot', @@ -67,7 +52,6 @@ let ModelEditor = PageView.extend({ }, initialize: function (attrs, options) { PageView.prototype.initialize.apply(this, arguments); - this.tooltips = Tooltips.modelEditor var self = this; let urlParams = new URLSearchParams(window.location.search) var directory = urlParams.get('path'); @@ -99,18 +83,6 @@ let ModelEditor = PageView.extend({ self.model.updateValid() } }) - this.model.reactions.on("change", function (reactions) { - this.updateSpeciesInUse(); - this.updateParametersInUse(); - }, this); - this.model.eventsCollection.on("add change remove", function (){ - this.updateSpeciesInUse(); - this.updateParametersInUse(); - }, this); - this.model.rules.on("add change remove", function() { - this.updateSpeciesInUse(); - this.updateParametersInUse(); - }, this); window.addEventListener("pageshow", function (event) { var navType = window.performance.navigation.type if(navType === 2){ @@ -118,10 +90,6 @@ let ModelEditor = PageView.extend({ } }); }, - update: function () { - }, - updateValid: function () { - }, getFileName: function (file) { if(file.endsWith('/')) { file.slice(0, -1) @@ -140,63 +108,6 @@ let ModelEditor = PageView.extend({ window.location.href = endpoint }, this)) }, - updateSpeciesInUse: function () { - var species = this.model.species; - var reactions = this.model.reactions; - var events = this.model.eventsCollection; - var rules = this.model.rules; - species.forEach(function (specie) { specie.inUse = false; }); - var updateInUseForReaction = function (stoichSpecie) { - _.where(species.models, { compID: stoichSpecie.specie.compID }) - .forEach(function (specie) { - specie.inUse = true; - }); - } - var updateInUseForOther = function (specie) { - _.where(species.models, { compID: specie.compID }) - .forEach(function (specie) { - specie.inUse = true; - }); - } - reactions.forEach(function (reaction) { - reaction.products.forEach(updateInUseForReaction); - reaction.reactants.forEach(updateInUseForReaction); - }); - events.forEach(function (event) { - event.eventAssignments.forEach(function (assignment) { - updateInUseForOther(assignment.variable) - }); - }); - rules.forEach(function (rule) { - updateInUseForOther(rule.variable); - }); - }, - updateParametersInUse: function () { - var parameters = this.model.parameters; - var reactions = this.model.reactions; - var events = this.model.eventsCollection; - var rules = this.model.rules; - parameters.forEach(function (param) { param.inUse = false; }); - var updateInUse = function (param) { - _.where(parameters.models, { compID: param.compID }) - .forEach(function (param) { - param.inUse = true; - }); - } - reactions.forEach(function (reaction) { - if(reaction.reactionType !== "custom-propensity"){ - updateInUse(reaction.rate); - } - }); - events.forEach(function (event) { - event.eventAssignments.forEach(function (assignment) { - updateInUse(assignment.variable) - }); - }); - rules.forEach(function (rule) { - updateInUse(rule.variable); - }); - }, renderParticleViewer: function (particle=null) { if(this.particleViewer) { this.particleViewer.remove(); @@ -213,19 +124,20 @@ let ModelEditor = PageView.extend({ }else{ $(this.queryByHook("me-select-particle")).css("display", "block") this.typeQuickViewer = this.renderCollection( - this.domainViewer.model.types, + this.modelView.domainViewer.model.types, QuickviewDomainTypes, this.queryByHook("me-types-quick-view") ); } }, + renderModelView: function () { + this.modelView = new ModelView({ + model: this.model + }); + app.registerRenderSubview(this, this.modelView, "model-view-container") + }, renderSubviews: function () { - if(this.model.defaultMode === "" && !this.model.is_spatial){ - this.getInitialDefaultMode(); - }else{ - let dataHooks = {'continuous':'all-continuous', 'discrete':'all-discrete', 'dynamic':'advanced'} - $(this.queryByHook(dataHooks[this.model.defaultMode])).prop('checked', true) - } + this.renderModelView() this.modelSettings = new TimespanSettingsView({ parent: this, model: this.model.modelSettings, @@ -233,30 +145,12 @@ let ModelEditor = PageView.extend({ this.modelStateButtons = new ModelStateButtonsView({ model: this.model }); - this.renderSpeciesView(); - this.renderParametersView(); - this.renderReactionsView(); app.registerRenderSubview(this, this.modelSettings, 'model-settings-container'); app.registerRenderSubview(this, this.modelStateButtons, 'model-state-buttons-container'); if(this.model.is_spatial) { - $(this.queryByHook("system-volume-container")).css("display", "none"); - $(this.queryByHook("advaced-model-mode")).css("display", "none"); $(this.queryByHook("spatial-beta-message")).css("display", "block"); - this.renderDomainViewer(); - this.renderInitialConditions(); - this.renderBoundaryConditionsView(); $(this.queryByHook("toggle-preview-domain")).css("display", "inline-block"); this.openDomainPlot(); - }else { - this.renderEventsView(); - this.renderRulesView(); - if(this.model.functionDefinitions.length) { - var sbmlComponentView = new SBMLComponentView({ - functionDefinitions: this.model.functionDefinitions - }); - app.registerRenderSubview(this, sbmlComponentView, 'sbml-component-container'); - } - this.renderSystemVolumeView(); } this.model.autoSave(); $(function () { @@ -269,111 +163,6 @@ let ModelEditor = PageView.extend({ e.target.remove() }); }, - renderBoundaryConditionsView: function() { - if(this.boundaryConditionsView) { - this.boundaryConditionsView.remove(); - } - this.boundaryConditionsView = new BoundaryConditionsView({ - collection: this.model.boundaryConditions - }); - app.registerRenderSubview(this, this.boundaryConditionsView, "boundary-conditions-container"); - }, - renderDomainViewer: function(domainPath=null) { - if(this.domainViewer) { - this.domainViewer.remove() - } - if(domainPath && domainPath !== "viewing") { - let self = this; - let queryStr = "?path=" + this.model.directory + "&domain_path=" + domainPath - let endpoint = path.join(app.getApiPath(), "spatial-model/load-domain") + queryStr - app.getXHR(endpoint, { - always: function (err, response, body) { - let domain = new Domain(body.domain); - self.domainViewer = new DomainViewer({ - parent: self, - model: domain, - domainPath: domainPath - }); - app.registerRenderSubview(self, self.domainViewer, 'domain-viewer-container'); - } - }); - }else{ - this.domainViewer = new DomainViewer({ - parent: this, - model: this.model.domain, - domainPath: domainPath - }); - app.registerRenderSubview(this, this.domainViewer, 'domain-viewer-container'); - } - }, - renderSpeciesView: function () { - if(this.speciesEditor) { - this.speciesEditor.remove() - } - this.speciesEditor = new SpeciesEditorView({ - collection: this.model.species, - spatial: this.model.is_spatial, - defaultMode: this.model.defaultMode - }); - app.registerRenderSubview(this, this.speciesEditor, 'species-editor-container'); - }, - renderInitialConditions: function () { - if(this.initialConditionsEditor) { - this.initialConditionsEditor.remove(); - } - this.initialConditionsEditor = new InitialConditionsEditorView({ - collection: this.model.initialConditions, - }); - app.registerRenderSubview(this, this.initialConditionsEditor, 'initial-conditions-editor-container'); - }, - renderParametersView: function () { - if(this.parametersEditor) { - this.parametersEditor.remove() - } - this.parametersEditor = new ParametersEditorView({collection: this.model.parameters}); - app.registerRenderSubview(this, this.parametersEditor, 'parameters-editor-container'); - }, - renderReactionsView: function () { - if(this.reactionsEditor) { - this.reactionsEditor.remove() - } - this.reactionsEditor = new ReactionsEditorView({collection: this.model.reactions}); - app.registerRenderSubview(this, this.reactionsEditor, 'reactions-editor-container'); - }, - renderEventsView: function () { - if(this.eventsEditor){ - this.eventsEditor.remove(); - } - this.eventsEditor = new EventsEditorView({collection: this.model.eventsCollection}); - app.registerRenderSubview(this, this.eventsEditor, 'events-editor-container'); - }, - renderRulesView: function () { - if(this.rulesEditor){ - this.rulesEditor.remove(); - } - this.rulesEditor = new RulesEditorView({collection: this.model.rules}); - app.registerRenderSubview(this, this.rulesEditor, 'rules-editor-container'); - }, - renderSystemVolumeView: function () { - if(this.systemVolumeView) { - this.systemVolumeView.remove() - } - this.systemVolumeView = new InputView ({ - parent: this, - required: true, - name: 'system-volume', - label: 'Volume: ', - tests: tests.valueTests, - modelKey: 'volume', - valueType: 'number', - value: this.model.volume, - }); - app.registerRenderSubview(this, this.systemVolumeView, 'edit-volume') - if(this.model.defaultMode === "continuous") { - $(this.queryByHook("system-volume-container")).collapse("hide") - } - $(this.queryByHook("view-volume")).html("Volume: " + this.model.volume) - }, changeCollapseButtonText: function (e) { app.changeCollapseButtonText(this, e); }, @@ -426,66 +215,6 @@ let ModelEditor = PageView.extend({ clickDownloadPNGButton: function (e) { let pngButton = $('div[data-hook=preview-plot-container] a[data-title*="Download plot as a png"]')[0] pngButton.click() - }, - getInitialDefaultMode: function () { - var self = this; - if(document.querySelector('#defaultModeModal')) { - document.querySelector('#defaultModeModal').remove(); - } - let modal = $(modals.renderDefaultModeModalHtml()).modal(); - let continuous = document.querySelector('#defaultModeModal .concentration-btn'); - let discrete = document.querySelector('#defaultModeModal .population-btn'); - let dynamic = document.querySelector('#defaultModeModal .hybrid-btn'); - continuous.addEventListener('click', function (e) { - self.setInitialDefaultMode(modal, "continuous"); - }); - discrete.addEventListener('click', function (e) { - self.setInitialDefaultMode(modal, "discrete"); - }); - dynamic.addEventListener('click', function (e) { - self.setInitialDefaultMode(modal, "dynamic"); - }); - }, - setAllSpeciesModes: function (prevMode) { - let self = this; - this.model.species.forEach(function (specie) { - specie.mode = self.model.defaultMode; - self.model.species.trigger('update-species', specie.compID, specie, false, true); - }); - let switchToDynamic = (!Boolean(prevMode) || prevMode !== "dynamic") && this.model.defaultMode === "dynamic"; - let switchFromDynamic = Boolean(prevMode) && prevMode === "dynamic" && this.model.defaultMode !== "dynamic"; - if(switchToDynamic || switchFromDynamic) { - this.speciesEditor.renderEditSpeciesView(); - this.speciesEditor.renderViewSpeciesView(); - } - }, - setDefaultMode: function (e) { - let prevMode = this.model.defaultMode; - this.model.defaultMode = e.target.dataset.name; - this.speciesEditor.defaultMode = e.target.dataset.name; - this.setAllSpeciesModes(prevMode); - this.toggleVolumeContainer(); - }, - setInitialDefaultMode: function (modal, mode) { - var dataHooks = {'continuous':'all-continuous', 'discrete':'all-discrete', 'dynamic':'advanced'}; - modal.modal('hide'); - $(this.queryByHook(dataHooks[mode])).prop('checked', true); - this.model.defaultMode = mode; - this.speciesEditor.defaultMode = mode; - this.setAllSpeciesModes(); - this.toggleVolumeContainer(); - }, - toggleVolumeContainer: function () { - if(!this.model.is_spatial) { - if(this.model.defaultMode === "continuous") { - $(this.queryByHook("system-volume-container")).collapse("hide"); - }else{ - $(this.queryByHook("system-volume-container")).collapse("show"); - } - } - }, - updateVolumeViewer: function (e) { - $(this.queryByHook("view-volume")).html("Volume: " + this.model.volume) } }); diff --git a/client/pages/model-presentation.js b/client/pages/model-presentation.js new file mode 100644 index 0000000000..e052b2d31a --- /dev/null +++ b/client/pages/model-presentation.js @@ -0,0 +1,79 @@ +/* +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +let $ = require('jquery'); +let path = require('path'); +let domReady = require('domready'); +let bootstrap = require('bootstrap'); +//support files +let app = require('../app'); +//models +let Model = require('../models/model'); +//views +let PageView = require('./base'); +let ModelView = require('../model-view/model-view'); +//templates +let template = require('../templates/pages/modelPresentation.pug'); + +import bootstrapStyles from '../styles/bootstrap.css'; +import styles from '../styles/styles.css'; +import fontawesomeStyles from '@fortawesome/fontawesome-free/css/svg-with-js.min.css' + +let ModelPresentationPage = PageView.extend({ + template: template, + initialize: function (attrs, options) { + PageView.prototype.initialize.apply(this, arguments); + let urlParams = new URLSearchParams(window.location.search); + let owner = urlParams.get("owner"); + let file = urlParams.get("file"); + this.model = new Model({ + directory: file, + for: "presentation" + }); + let self = this; + let queryStr = "?file=" + this.model.directory + "&owner=" + owner; + let endpoint = "api/file/json-data" + queryStr; + app.getXHR(endpoint, { + success: function (err, response, body) { + self.model.set(body); + self.renderSubviews(); + } + }); + let downloadStart = "https://live.stochss.org/stochss/download_presentation"; + this.downloadLink = downloadStart + "/" + owner + "/" + file; + this.openLink = "https://open.stochss.org?open=" + this.downloadLink; + }, + renderSubviews: function () { + PageView.prototype.render.apply(this, arguments); + this.renderModelView(); + }, + renderModelView: function () { + let modelView = ModelView({ + model: this.model, + readOnly: true + }); + app.registerRenderSubview(this, modelView, "model-view"); + } +}); + +domReady(() => { + let p = new ModelPresentationPage({ + el: document.body + }); + p.render(); +}); diff --git a/client/pages/notebook-presentation.js b/client/pages/notebook-presentation.js new file mode 100644 index 0000000000..932b2175bc --- /dev/null +++ b/client/pages/notebook-presentation.js @@ -0,0 +1,75 @@ +/* +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +let $ = require('jquery'); +let path = require('path'); +let domReady = require('domready'); +let bootstrap = require('bootstrap'); +//support files +let app = require('../app'); +//views +let PageView = require('./base'); +//templates +let template = require('../templates/pages/notebookPresentation.pug'); + +import bootstrapStyles from '../styles/bootstrap.css'; +import styles from '../styles/styles.css'; +import fontawesomeStyles from '@fortawesome/fontawesome-free/css/svg-with-js.min.css' + +let NotebookPresentationPage = PageView.extend({ + template: template, + initialize: function (attrs, options) { + PageView.prototype.initialize.apply(this, arguments); + let urlParams = new URLSearchParams(window.location.search); + let owner = urlParams.get("owner"); + let file = urlParams.get("file"); + let self = this; + let queryStr = "?owner=" + owner + "&file=" + file; + let endpoint = "api/notebook/load" + queryStr; + app.getXHR(endpoint, { + success: function (err, response, body) { + self.name = body.file.split('/').pop().split('.ipynb')[0]; + self.renderSubviews(body.html); + } + }); + let downloadStart = "https://live.stochss.org/stochss/notebook/download_presentation"; + this.downloadLink = downloadStart + "/" + owner + "/" + file; + this.openLink = "https://open.stochss.org?open=" + this.downloadLink; + }, + renderSubviews: function (html) { + PageView.prototype.render.apply(this, arguments); + let iframe = document.getElementById('notebook'); + let iframedoc = iframe.document; + if (iframe.contentDocument) { + iframedoc = iframe.contentDocument; + }else if (iframe.contentWindow) { + iframedoc = iframe.contentWindow.document; + } + if (iframedoc) { + iframedoc.write(html); + iframedoc.close(); + } + } +}); + +domReady(() => { + let p = new NotebookPresentationPage({ + el: document.body + }); + p.render(); +}); diff --git a/client/pages/workflow-manager.js b/client/pages/workflow-manager.js index 0e1696a6b0..42c982255a 100644 --- a/client/pages/workflow-manager.js +++ b/client/pages/workflow-manager.js @@ -29,9 +29,9 @@ let PageView = require('./base'); let SettingsView = require('../views/settings'); let LogsView = require('../views/workflow-info'); let SelectView = require('ampersand-select-view'); +let ModelView = require('../model-view/model-view'); let StatusView = require('../views/workflow-status'); let JobListingView = require('../views/job-listing'); -let ModelViewerView = require('../views/model-viewer'); let ResultsView = require('../views/workflow-results'); let SettingsViewerView = require('../views/settings-viewer'); //templates @@ -47,6 +47,7 @@ let WorkflowManager = PageView.extend({ 'click [data-hook=project-breadcrumb]' : 'handleReturnToProject', 'click [data-hook=save-model]' : 'handleSaveWorkflow', 'click [data-hook=collapse-jobs]' : 'changeCollapseButtonText', + 'click [data-hook=collapse-model]' : 'changeCollapseButtonText', 'click [data-hook=return-to-project-btn]' : 'handleReturnToProject' }, initialize: function (attrs, options) { @@ -146,7 +147,7 @@ let WorkflowManager = PageView.extend({ } if(this.logsView) { this.logsView.remove(); - this.modelViewerView.remove(); + this.modelView.remove(); this.settingsViewerView.remove(); } }, @@ -160,7 +161,7 @@ let WorkflowManager = PageView.extend({ } this.renderLogsView(); this.renderSettingsViewerView(); - this.renderModelViewerView(); + this.renderModelView(); }, renderJobListingView: function () { if(this.jobListingView) { @@ -208,14 +209,17 @@ let WorkflowManager = PageView.extend({ }); app.registerRenderSubview(this, modelSelectView, "model-file"); }, - renderModelViewerView: function () { - if(this.modelViewerView) { - this.modelViewerView.remove(); + renderModelView: function () { + if(this.modelView) { + this.modelView.remove(); } - this.modelViewerView = new ModelViewerView({ - model: this.model.activeJob.model + let header = "Review Model: " + this.model.activeJob.model.name; + $("#model-viewer-header").html(header); + this.modelView = new ModelView({ + model: this.model.activeJob.model, + readOnly: true }); - app.registerRenderSubview(this, this.modelViewerView, "model-viewer-container"); + app.registerRenderSubview(this, this.modelView, "model-viewer-container"); }, renderResultsView: function () { if(this.resultsView) { diff --git a/client/styles/styles.css b/client/styles/styles.css index 64935dff14..f9d28c9eb0 100644 --- a/client/styles/styles.css +++ b/client/styles/styles.css @@ -339,10 +339,9 @@ input[type="file"]::-ms-browse { .btn-outline-collapse { color: #000; - padding: 0px 10px; + padding: 0px 10px 6px 10px; font-size: 20px; vertical-align: middle; - margin-bottom: 0.75rem; } .btn-outline-collapse:hover { @@ -554,6 +553,13 @@ span.checkbox { border-radius: 1.5rem; } +.register-stochss-btn { + padding: 1.5rem 1.5rem; + font-size: 1.75rem; + line-height: 1; + border-radius: 1.5rem; +} + .user-home-btn { padding: 1rem 1rem; font-size: 1.5rem; @@ -706,3 +712,8 @@ span.checkbox { .card-header { background-color: rgba(0, 0, 0, 0.1); } + +.presentation-header { + margin-top: 64px; + padding: 20px 16px; +} diff --git a/client/templates/includes/gillespyResults.pug b/client/templates/includes/gillespyResults.pug index 354ec74d2a..ec7dc3f17e 100644 --- a/client/templates/includes/gillespyResults.pug +++ b/client/templates/includes/gillespyResults.pug @@ -63,3 +63,19 @@ div#workflow-results.card.card-body button.btn.btn-primary.box-shadow(id="convert-to-notebook" data-hook="convert-to-notebook") Convert to Notebook button.btn.btn-primary.box-shadow(id="download-results-csv" data-hook="download-results-csv") Download Results as .csv + + button.btn.btn-primary.box-shadow(id="job-presentation" data-hook="job-presentation") Publish + + div.saving-status(data-hook="job-action-start") + + div.spinner-grow + + span Publishing ... + + div.saved-status(data-hook="job-action-end") + + span Published + + div.save-error-status(data-hook="job-action-err") + + span Error diff --git a/client/templates/includes/gillespyResultsEnsemble.pug b/client/templates/includes/gillespyResultsEnsemble.pug index 48186f5fb7..87282e234a 100644 --- a/client/templates/includes/gillespyResultsEnsemble.pug +++ b/client/templates/includes/gillespyResultsEnsemble.pug @@ -176,3 +176,19 @@ div#workflow-results.card.card-body button.btn.btn-primary.box-shadow(id="convert-to-notebook" data-hook="convert-to-notebook") Convert to Notebook button.btn.btn-primary.box-shadow(id="download-results-csv" data-hook="download-results-csv") Download Results as .csv + + button.btn.btn-primary.box-shadow(id="job-presentation" data-hook="job-presentation") Publish + + div.saving-status(data-hook="job-action-start") + + div.spinner-grow + + span Publishing ... + + div.saved-status(data-hook="job-action-end") + + span Published + + div.save-error-status(data-hook="job-action-err") + + span Error diff --git a/client/templates/includes/initialConditionsViewer.pug b/client/templates/includes/initialConditionsViewer.pug deleted file mode 100644 index deb22b01b6..0000000000 --- a/client/templates/includes/initialConditionsViewer.pug +++ /dev/null @@ -1,28 +0,0 @@ -div#initial-conditions.card.card-body - - div - - h3.inline Initial Conditions - - button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#initial-condition" data-hook="initial-condition-button") - - - div.collapse.show(id="initial-condition" data-hook="initial-conditions") - - table.table - - thead - - tr - - th(scope="col") Type - - th(scope="col") Variable - - th(scope="col") Count - - th(scope="col") Details - - tbody(data-hook="initial-conditions-collection") - - if this.collection.parent.for === "edit" - button.btn.btn-outline-primary.box-shadow(data-hook="edit-species") Edit Variables \ No newline at end of file diff --git a/client/templates/includes/modelStateButtons.pug b/client/templates/includes/modelStateButtons.pug index e5f340e678..5cc08474a9 100644 --- a/client/templates/includes/modelStateButtons.pug +++ b/client/templates/includes/modelStateButtons.pug @@ -1,14 +1,22 @@ div.mdl-edit-btn - div.mdl-edit-btn.saving-status(data-hook="saving-mdl") + div.mdl-edit-btn.saving-status(data-hook="mdl-action-start") div.spinner-grow - span Saving... + span(data-hook="saving" style="display: none") Saving ... - div.mdl-edit-btn.saved-status(data-hook="saved-mdl") + span(data-hook="publishing" style="display: none") Publishing ... - span Saved + div.mdl-edit-btn.saved-status(data-hook="mdl-action-end") + + span(data-hook="saved" style="display: none") Saved + + span(data-hook="published" style="display: none") Published + + div.mdl-edit-btn.save-error-status(data-hook="mdl-action-err") + + span Error button.btn.btn-primary.box-shadow(data-hook="save") Save @@ -29,4 +37,6 @@ div.mdl-edit-btn li.dropdown-item(id="stochss-es" data-hook="stochss-es" data-type="ensemble") Ensemble Simulation li.dropdown-item(id="stochss-ps" data-hook="stochss-ps" data-type="psweep") Parameter Sweep li.dropdown-item(data-hook="new-workflow" data-type="notebook") Jupyter Notebook + + button.btn.btn-primary.box-shadow(data-hook="presentation") Publish \ No newline at end of file diff --git a/client/templates/includes/modelViewer.pug b/client/templates/includes/modelViewer.pug deleted file mode 100644 index 9559e2a1f8..0000000000 --- a/client/templates/includes/modelViewer.pug +++ /dev/null @@ -1,23 +0,0 @@ -div.card.card-body - - div(id="model-viewer-header") - - h3.inline="Review Model: "+this.model.name - - button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-model" data-hook="collapse-model") + - - div.collapse(id="collapse-model") - - div(data-hook="species-viewer-container") - - div(data-hook="parameters-viewer-container") - - div(data-hook="reactions-viewer-container") - - div(data-hook="events-viewer-container") - - div(data-hook="rules-viewer-container") - - div(data-hook="sbml-components-viewer-container") - - div.card.card-body="System Volume: "+this.model.volume diff --git a/client/templates/includes/parameterScanResults.pug b/client/templates/includes/parameterScanResults.pug index 2f6efea14b..7c02d2860e 100644 --- a/client/templates/includes/parameterScanResults.pug +++ b/client/templates/includes/parameterScanResults.pug @@ -80,3 +80,18 @@ div#workflow-results.card.card-body div.mt-2(data-hook="parameter-ranges") + button.btn.btn-primary.box-shadow(id="job-presentation" data-hook="job-presentation") Publish Presentation + + div.saving-status(data-hook="job-action-start") + + div.spinner-grow + + span Publishing ... + + div.saved-status(data-hook="job-action-end") + + span Published + + div.save-error-status(data-hook="job-action-err") + + span Error diff --git a/client/templates/includes/parameterSweepResults.pug b/client/templates/includes/parameterSweepResults.pug index 3df6edbb08..ccd407c306 100644 --- a/client/templates/includes/parameterSweepResults.pug +++ b/client/templates/includes/parameterSweepResults.pug @@ -160,3 +160,19 @@ div#workflow-results.card.card-body button.btn.btn-primary.box-shadow(id="convert-to-notebook" data-hook="convert-to-notebook") Convert to Notebook button.btn.btn-primary.box-shadow(id="download-results-csv" data-hook="download-results-csv") Download Results as .csv + + button.btn.btn-primary.box-shadow(id="job-presentation" data-hook="job-presentation") Publish + + div.saving-status(data-hook="job-action-start") + + div.spinner-grow + + span Publishing ... + + div.saved-status(data-hook="job-action-end") + + span Published + + div.save-error-status(data-hook="job-action-err") + + span Error diff --git a/client/templates/includes/settingsViewer.pug b/client/templates/includes/settingsViewer.pug index 90ba4f0528..b4875f85a5 100644 --- a/client/templates/includes/settingsViewer.pug +++ b/client/templates/includes/settingsViewer.pug @@ -2,7 +2,7 @@ div#workflow-settings-viewer.card.card-body div - h3.inline Review Settings + h3.inline(data-hook="job-settings-header") Review Settings button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-wkfl-settings-viewer" data-hook="collapse-settings-viewer") + diff --git a/client/templates/pages/home.pug b/client/templates/pages/home.pug index 49b2d48185..47b87ae585 100644 --- a/client/templates/pages/home.pug +++ b/client/templates/pages/home.pug @@ -1,58 +1,49 @@ -html +section.page + div#home-wrapper.container.card.card-body + + div.logo(id="stochss-logo" data-hook="stochss-logo") + img(src="/hub/static/stochss-logo.png") - head - meta(charset="utf-8") - title StochSS: Stochastic Simulation Service - meta(name="viewport", content="width=device-width, initial-scale=1.0") - meta(name="description", content="") - meta(name="author", content="") + div.centered + h1.display-5 Welcome to StochSS Live! - body - div#home-wrapper.container.card.card-body - - div.logo(id="stochss-logo" data-hook="stochss-logo") - img(src="/hub/static/stochss-logo.png") + p.home-p + | An accessible platform for modeling mathematical, biological, and biochemical systems. - div.centered - h1.display-5 Welcome to StochSS Live! + div.row.home-highlights + div.col-md-2 + div.col-md-5 - p.home-p - | An accessible platform for modeling mathematical, biological, and biochemical systems. + h5 Features + ul.home-list + li Discrete Stochastic Modeling + li Continuous ODE Modeling + li Convert Between Stochastic and ODE Models + li Import SBML Models + li Parameter Sweep Workflows + li Spatial Simulations + + div.col-md-5 - div.row.home-highlights - div.col-md-2 - div.col-md-5 + h5 Coming soon... + ul.home-list + li Sciope Integration + li Bring Your Own Cloud - h5 Features - ul.home-list - li Discrete Stochastic Modeling - li Continuous ODE Modeling - li Convert Between Stochastic and ODE Models - li Import SBML Models - li Parameter Sweep Workflows - li Spatial Simulations - - div.col-md-5 + div.centered + a.try-stochss-btn.btn.btn-primary.box-shadow(href="/hub/spawn" role="button") Click here to login - h5 Coming soon... - ul.home-list - li Sciope Integration - li Bring Your Own Cloud + div#registration-home.container.card.card-body - div.centered - a.try-stochss-btn.btn.btn-primary.box-shadow(href="/hub/spawn" role="button") Click here to login + div.centered - div#registration-home.container.card.card-body + p.home-p + | StochSS is open-source software. To obtain continued funding for sustained development, we must show that StochSS is making an impact in the scientific community. For this, we need to know who is using the software, and a bit about what they are using it for. Please consider registering StochSS to show your support. - div.centered + div.collapse.show(data-hook="registration-link") - p.home-p - | StochSS is open-source software. To obtain continued funding for sustained development, we must show that StochSS is making an impact in the scientific community. For this, we need to know who is using the software, and a bit about what they are using it for. Please consider registering StochSS to show your support. + button.register-stochss-btn.btn.btn-primary.box-shadow(data-hook="registration-link-button" style="margin: 1.5rem;") Register Stochss - div.collapse(data-hook="registration-link") + div.collapse(data-hook="registration-form" id="registration-form") - button.btn.btn-primary.box-shadow(data-hook="registration-link-button" style="margin: 1.5rem;") Register Stochss - - div.collapse.show(data-hook="registration-form" id="registration-form") - - iframe(src="https://docs.google.com/forms/d/12tAH4f8CJ-3F-lK44Q9uQHFio_mGoK0oY829q5lD7i4/viewform?embedded=true" width="100%" height="800" frameborder="0") + iframe(src="https://docs.google.com/forms/d/12tAH4f8CJ-3F-lK44Q9uQHFio_mGoK0oY829q5lD7i4/viewform?embedded=true" width="100%" height="800" frameborder="0") diff --git a/client/templates/pages/jobPresentation.pug b/client/templates/pages/jobPresentation.pug new file mode 100644 index 0000000000..34e51b0375 --- /dev/null +++ b/client/templates/pages/jobPresentation.pug @@ -0,0 +1,13 @@ +section.page + + div#job-presentation.container + + h2=this.model.name + + div(data-hook="job-results") + + div(data-hook="job-settings") + + div(data-hook="job-model") + + a.btn.btn-outline-secondary.box-shadow.text-break(href=this.open role="button") Open in StochSS \ No newline at end of file diff --git a/client/templates/pages/modelEditor.pug b/client/templates/pages/modelEditor.pug index 1c1d3cc683..2d30773d17 100644 --- a/client/templates/pages/modelEditor.pug +++ b/client/templates/pages/modelEditor.pug @@ -26,94 +26,7 @@ section.page ol.breadcrumb li.breadcrumb-item.active(aria-current="page")=this.model.name - div.card - - div.card-header.pb-0 - - h3.inline Model Mode - - div.tooltip-icon(data-html="true" data-toggle="tooltip" title=this.tooltips.modelMode) - - div.card-body - div.row - div.col-sm-4 - input.mr-2(type="radio" name="default-mode" data-hook="all-continuous" data-name="continuous") - span Concentration - div.col-sm-4 - input.mr-2(type="radio" name="default-mode" data-hook="all-discrete" data-name="discrete") - span Population - div.col-sm-4(data-hook="advaced-model-mode") - input.mr-2(type="radio" name="default-mode" data-hook="advanced" data-name="dynamic") - span Hybrid Concentration/Population - - div(data-hook="domain-viewer-container") - - div(data-hook="species-editor-container") - - div(data-hook="initial-conditions-editor-container") - - div(data-hook="parameters-editor-container") - - div(data-hook="reactions-editor-container") - - div.card(data-hook="model-editor-advanced-container") - - div.card-header.pb-0 - - h3.inline Advanced - - button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#me-advanced-section", data-hook="collapse-me-advanced-section") + - - div.collapse(id="me-advanced-section", data-hook="me-advanced-section") - - div.card-body - - div(data-hook="events-editor-container") - - div(data-hook="rules-editor-container") - - div(data-hook="boundary-conditions-container") - - div(data-hook="sbml-component-container") - - div.card.collapse.show(data-hook="system-volume-container") - - div.card-header.pb-0 - - h3.inline.mr-3 System Volume - - div.inline.mr-3 - - ul.nav.nav-tabs.card-header-tabs(id="volume-tabs") - - li.nav-item - - a.nav-link.tab.active(data-hook="volume-edit-tab" data-toggle="tab" href="#edit-system-volume") Edit - - li.nav-item - - a.nav-link.tab(data-hook="volume-view-tab" data-toggle="tab" href="#view-system-volume") View - - button.btn.btn-outline-collapse(data-toggle="collapse", data-target="#collapse-system-volume", data-hook="collapse-system-volume") + - - div.card-body - - p.mb-0 - | System volume affects custom propensities or stochastic reactions with two reactants. The volume sets the implicit parameter 'vol' which can be used in custom propensity functions. A single well-mixed volume is assumed. Compartments are not currently supported. In most cases this should not be changed. please review your model requirements carefully before changing this property. - - div.collapse.tab-content(id="collapse-system-volume" data-hook="system-volume-section") - - div.tab-pane.active(id="edit-system-volume" data-hook="edit-system-volume") - - hr - - div(data-hook="edit-volume") - - div.tab-pane(id="view-system-volume" data-hook="view-system-volume") - - hr - - div(data-hook="view-volume") + div(data-hook="model-view-container") div(data-hook="model-settings-container") diff --git a/client/templates/pages/modelPresentation.pug b/client/templates/pages/modelPresentation.pug new file mode 100644 index 0000000000..f5735e7810 --- /dev/null +++ b/client/templates/pages/modelPresentation.pug @@ -0,0 +1,43 @@ +section.page + + nav.navbar.navbar-expand-md.p-1.navbar-light.bg-light.fixed-top + a.navbar-brand(href="/hub/spawn") + img(style="height: 38px;margin-left: -1.2em;" src="/hub/static/stochss-logo.png") + + button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation") + span.navbar-toggler-icon + + div#navbar.collapse.navbar-collapse.justify-content-end(role="navigation") + ul.navbar-nav.float-right + li.nav-item: a.nav-link(href="http://www.stochss.org", target="_blank") + | About + + li.nav-item: a.nav-link(href="https://docs.google.com/forms/d/12tAH4f8CJ-3F-lK44Q9uQHFio_mGoK0oY829q5lD7i4/viewform?embedded=true", target="_blank") + | Register + + li.nav-item: a.nav-link(href="http://www.stochss.org/documentation", target="_blank") + | Documentation + + li.nav-item: a.nav-link(href="https://forms.gle/hpGJ1ruxR7wTT43h8" target="_blank") + | Submit Feedback + + li.nav-item + div.dropdown + button.dropdown-toggle.nav-item.nav-link.dropbtn Contact + div.dropdown-content + a.nav-link(href="https://gitter.im/StochSS/community#", target="_blank") Community Chat + a.nav-link(href="https://github.com/StochSS/stochss/issues/new", target="_blank") Report Issue + + div#model-presentation.container + + div.presentation-header + + h1=this.model.name + + div(data-hook="model-view") + + div.mt-3 + + a.btn.btn-outline-secondary.box-shadow.text-break.mr-3(href=this.openLink role="button") Open in StochSS + + a.btn.btn-outline-secondary.box-shadow.text-break(href=this.downloadLink role="button") Download (.mdl) diff --git a/client/templates/pages/notebookPresentation.pug b/client/templates/pages/notebookPresentation.pug new file mode 100644 index 0000000000..ba03a11038 --- /dev/null +++ b/client/templates/pages/notebookPresentation.pug @@ -0,0 +1,45 @@ +section.page + + nav.navbar.navbar-expand-md.p-1.navbar-light.bg-light.fixed-top + a.navbar-brand(href="/hub/spawn") + img(style="height: 38px;margin-left: -1.2em;" src="/hub/static/stochss-logo.png") + + button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbar" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation") + span.navbar-toggler-icon + + div#navbar.collapse.navbar-collapse.justify-content-end(role="navigation") + ul.navbar-nav.float-right + li.nav-item: a.nav-link(href="http://www.stochss.org", target="_blank") + | About + + li.nav-item: a.nav-link(href="https://docs.google.com/forms/d/12tAH4f8CJ-3F-lK44Q9uQHFio_mGoK0oY829q5lD7i4/viewform?embedded=true", target="_blank") + | Register + + li.nav-item: a.nav-link(href="http://www.stochss.org/documentation", target="_blank") + | Documentation + + li.nav-item: a.nav-link(href="https://forms.gle/hpGJ1ruxR7wTT43h8" target="_blank") + | Submit Feedback + + li.nav-item + div.dropdown + button.dropdown-toggle.nav-item.nav-link.dropbtn Contact + div.dropdown-content + a.nav-link(href="https://gitter.im/StochSS/community#", target="_blank") Community Chat + a.nav-link(href="https://github.com/StochSS/stochss/issues/new", target="_blank") Report Issue + + div#notebook-presentation.container + + div.presentation-header + + h1=this.name + + div.card.card-body + + iframe(id="notebook" width="100%" height="100%" frameborder="0" onload="this.height=this.contentWindow.document.body.scrollHeight;") + + div.mt-3 + + a.btn.btn-outline-secondary.box-shadow.text-break.mr-3(href=this.openLink role="button") Open in StochSS + + a.btn.btn-outline-secondary.box-shadow.text-break(href=this.downloadLink role="button") Download (.ipynb) diff --git a/client/templates/pages/workflowManager.pug b/client/templates/pages/workflowManager.pug index b4f85bdb30..ff45f09c82 100644 --- a/client/templates/pages/workflowManager.pug +++ b/client/templates/pages/workflowManager.pug @@ -69,9 +69,19 @@ section.page div(data-hook="settings-viewer-container") - div(data-hook="model-viewer-container") + div.card - div(data-hook="computational-resources-container") + div.card-header + + h3.inline(id="model-viewer-header") "Review Model: " + + button.btn.btn-outline-collapse(data-toggle="collapse" data-target="#collapse-model" data-hook="collapse-model") + + + div.collapse(id="collapse-model") + + div.card-body(data-hook="model-viewer-container") + + div.mb-2(data-hook="computational-resources-container") button.btn.btn-primary.box-shadow(data-hook="return-to-project-btn" style="display: none;") Return to Project diff --git a/client/tooltips.js b/client/tooltips.js index 56fc32971c..5a5f014956 100644 --- a/client/tooltips.js +++ b/client/tooltips.js @@ -17,13 +17,6 @@ along with this program. If not, see . */ module.exports = { - modelEditor: { - modelMode: "Concentration - Variables will only be represented using continuous (floating point) values.
Population - Variables will only be represented "+ - "using discrete (integer count) values.
Hybrid Concentration/Population - Allows a variables to be represented using continuous and/or discrete values.", - - spatialModelMode: "Concentration - Variables will only be represented using continuous (floating point) values.
Population - Variables will only be represented "+ - "using discrete (integer count) values." - }, speciesEditor: { name: "Unique identifier for Variable. Cannot share a name with other model components.", diff --git a/client/views/file-browser-view.js b/client/views/file-browser-view.js index b60f2bf2b9..edb54b2307 100644 --- a/client/views/file-browser-view.js +++ b/client/views/file-browser-view.js @@ -942,6 +942,22 @@ module.exports = View.extend({ } }); }, + publishNotebookPresentation: function (o) { + let queryStr = "?path=" + o.original._path; + let endpoint = path.join(app.getApiPath(), "notebook/presentation") + queryStr; + app.getXHR(endpoint, { + success: function (err, response, body) { + let title = body.message; + let linkHeaders = ["Presentation Link", "Download Link", "Open Link"]; + let links = body.links; + let name = o.original._path.split('/').pop().split('.ipynb')[0]; + $(modals.presentationLinks(title, name, linkHeaders, links)).modal(); + }, + error: function (err, response, body) { + $(modals.newProjectModelErrorHtml(body.Reason, body.Message)).modal(); + } + }); + }, setupJstree: function () { var self = this; $.jstree.defaults.contextmenu.items = (o, cb) => { @@ -1373,6 +1389,17 @@ module.exports = View.extend({ } } } + let notebook = { + "publish" : { + "label" : "Publish", + "_disabled" : false, + "separator_before" : false, + "separator_after" : false, + "action" : function (data) { + self.publishNotebookPresentation(o); + } + } + } if (o.type === 'root'){ return $.extend(refresh, project, commonFolder, downloadWCombine, {"Rename": common.Rename}) } @@ -1400,7 +1427,13 @@ module.exports = View.extend({ if (o.text.endsWith(".zip")) { return $.extend(open, extractAll, download, common) } - if (o.type === 'notebook' || o.type === "other") { + if (o.type === 'notebook') { + if(app.getBasePath() === "/") { + return $.extend(open, download, common) + } + return $.extend(open, notebook, download, common) + } + if (o.type === 'other') { return $.extend(open, download, common) } if (o.type === 'sbml-model') { diff --git a/client/views/initial-conditions-viewer.js b/client/views/initial-conditions-viewer.js deleted file mode 100644 index 66bfc3e51f..0000000000 --- a/client/views/initial-conditions-viewer.js +++ /dev/null @@ -1,54 +0,0 @@ -/* -StochSS is a platform for simulating biochemical systems -Copyright (C) 2019-2021 StochSS developers. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -var $ = require('jquery'); -//support files -let app = require('../app'); -//views -var View = require('ampersand-view'); -var ViewInitialCondition = require('./view-initial-condition'); -//templates -var template = require('../templates/includes/initialConditionsViewer.pug'); - -module.exports = View.extend({ - template: template, - events: { - 'click [data-hook=initial-condition-button]' : 'changeCollapseButtonText', - 'click [data-hook=edit-species]' : 'switchToEditMode' - }, - initialize: function (attrs, options) { - View.prototype.initialize.apply(this, arguments); - this.containsMdlWithAnn = this.collection.filter(function (model) {return model.annotation}).length > 0 - }, - render: function () { - View.prototype.render.apply(this, arguments); - this.renderCollection(this.collection, ViewInitialCondition, this.queryByHook('initial-conditions-collection')) - $(document).ready(function () { - $('[data-toggle="tooltip"]').tooltip(); - $('[data-toggle="tooltip"]').click(function () { - $('[data-toggle="tooltip"]').tooltip("hide"); - }); - }); - }, - switchToEditMode: function (e) { - this.parent.renderInitialConditions("edit", true); - }, - changeCollapseButtonText: function (e) { - app.changeCollapseButtonText(this, e); - }, -}); \ No newline at end of file diff --git a/client/views/model-state-buttons.js b/client/views/model-state-buttons.js index 82f4e40412..133903da50 100644 --- a/client/views/model-state-buttons.js +++ b/client/views/model-state-buttons.js @@ -19,6 +19,7 @@ along with this program. If not, see . var path = require('path'); var Plotly = require('../lib/plotly'); var $ = require('jquery'); +let _ = require('underscore'); //support file var app = require('../app'); var modals = require('../modals'); @@ -35,7 +36,8 @@ module.exports = View.extend({ "click [data-hook=stochss-es]" : "handleSimulateClick", "click [data-hook=stochss-ps]" : "handleSimulateClick", 'click [data-hook=new-workflow]' : 'handleSimulateClick', - 'click [data-hook=return-to-project-btn]' : 'clickReturnToProjectHandler' + 'click [data-hook=return-to-project-btn]' : 'clickReturnToProjectHandler', + 'click [data-hook=presentation]' : 'handlePresentationClick' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); @@ -48,10 +50,14 @@ module.exports = View.extend({ if(this.model.is_spatial) { $(this.queryByHook("stochss-es")).addClass("disabled"); $(this.queryByHook("stochss-ps")).addClass("disabled"); + $(this.queryByHook("presentation")).css("display", "none"); + }else if(app.getBasePath() === "/") { + $(this.queryByHook("presentation")).css("display", "none"); } }, clickSaveHandler: function (e) { - this.saveModel(this.saved.bind(this)); + let self = this; + this.saveModel(_.bind(self.endAction, self, "save")); }, clickRunHandler: function (e) { if(this.model.is_spatial && $(this.queryByHook("domain-plot-viewer-container")).css("display") !== "none") { @@ -71,7 +77,7 @@ module.exports = View.extend({ clickReturnToProjectHandler: function (e) { let self = this this.saveModel(function () { - self.saved() + self.endAction("save") var dirname = path.dirname(self.model.directory) if(dirname.endsWith(".wkgp")) { dirname = path.dirname(dirname) @@ -83,7 +89,7 @@ module.exports = View.extend({ clickNewWorkflowHandler: function (e) { let self = this this.saveModel(function () { - self.saved() + self.endAction("save") var queryString = "?path="+self.model.directory if(self.model.directory.includes('.proj')) { let wkgp = self.model.directory.includes('.wkgp') ? self.model.name + ".wkgp" : "WorkflowGroup1.wkgp" @@ -95,7 +101,7 @@ module.exports = View.extend({ }) }, getPreviewTarget: function () { - this.saved(); + this.endAction("save"); let species = this.model.species.map(function (species) { return species.name }); @@ -125,7 +131,7 @@ module.exports = View.extend({ } }, saveModel: function (cb) { - this.saving(); + this.startAction("save"); // this.model is a ModelVersion, the parent of the collection is Model var model = this.model; if (cb) { @@ -134,24 +140,50 @@ module.exports = View.extend({ model.saveModel(); } }, - saving: function () { - var saving = this.queryByHook('saving-mdl'); - var saved = this.queryByHook('saved-mdl'); + startAction: function (action) { + if(action === "save") { + msg = $(this.queryByHook("saving")); + }else{ + msg = $(this.queryByHook("publishing")); + } + msg.css("display", "inline-block"); + var saving = this.queryByHook('mdl-action-start'); + var saved = this.queryByHook('mdl-action-end'); saved.style.display = "none"; saving.style.display = "inline-block"; }, - saved: function () { - var saving = this.queryByHook('saving-mdl'); - var saved = this.queryByHook('saved-mdl'); + errorAction: function () { + oldMsg = $(this.queryByHook("publishing")).css("display", "none"); + var saving = this.queryByHook('mdl-action-start'); + var error = this.queryByHook('mdl-action-err'); + saving.style.display = "none"; + error.style.display = "inline-block"; + setTimeout(function () { + error.style.display = "none"; + }, 5000); + }, + endAction: function (action) { + if(action === "save") { + oldMsg = $(this.queryByHook("saving")); + msg = $(this.queryByHook("saved")); + }else{ + oldMsg = $(this.queryByHook("publishing")); + msg = $(this.queryByHook("published")); + } + oldMsg.css("display", "none"); + msg.css("display", "inline-block"); + var saving = this.queryByHook('mdl-action-start'); + var saved = this.queryByHook('mdl-action-end'); saving.style.display = "none"; saved.style.display = "inline-block"; setTimeout(function () { saved.style.display = "none"; + msg.css("display", "none"); }, 5000); }, runModel: function (target=null) { if(typeof target !== "string") { - this.saved(); + this.endAction("save"); } this.running(); $(this.parent.queryByHook('model-run-container')).css("display", "block") @@ -238,12 +270,15 @@ module.exports = View.extend({ Plotly.newPlot(el, data); window.scrollTo(0, document.body.scrollHeight) }, + displayError: function (errorMsg, e) { + $(this.parent.queryByHook('toggle-preview-plot')).click() + errorMsg.css('display', 'block') + this.focusOnError(e) + }, handleSimulateClick: function (e) { var errorMsg = $(this.parent.queryByHook("error-detected-msg")) if(!this.model.valid) { - $(this.parent.queryByHook('toggle-preview-plot')).click() - errorMsg.css('display', 'block') - this.focusOnError(e) + this.displayError(errorMsg, e); }else{ errorMsg.css('display', 'none') let simType = e.target.dataset.type @@ -260,6 +295,31 @@ module.exports = View.extend({ } } }, + handlePresentationClick: function (e) { + var errorMsg = $(this.parent.queryByHook("error-detected-msg")); + if(!this.model.valid) { + this.displayError(errorMsg, e); + }else{ + let self = this; + this.startAction("publish") + let queryStr = "?path=" + this.model.directory; + let endpoint = path.join(app.getApiPath(), "model/presentation") + queryStr; + app.getXHR(endpoint, { + success: function (err, response, body) { + self.endAction("publish"); + let title = body.message; + let linkHeaders = ["Presentation Link", "Download Link", "Open Link"]; + let links = body.links; + let name = self.model.name + $(modals.presentationLinks(title, name, linkHeaders, links)).modal(); + }, + error: function (err, response, body) { + self.errorAction(); + $(modals.newProjectModelErrorHtml(body.Reason, body.Message)).modal(); + } + }); + } + }, focusOnError: function (e) { if(this.model.error) { let self = this @@ -294,34 +354,34 @@ module.exports = View.extend({ } }, openSpeciesSection: function () { - let specSection = $(this.parent.speciesEditor.queryByHook("species-list-container")) + let specSection = $(this.parent.modelView.speciesView.queryByHook("species-list-container")) if(!specSection.hasClass("show")) { - let specCollapseBtn = $(this.parent.speciesEditor.queryByHook("collapse")) + let specCollapseBtn = $(this.parent.modelView.speciesView.queryByHook("collapse")) specCollapseBtn.click() specCollapseBtn.html('-') } }, openDomainSection: function () { - let domainSection = $(this.parent.parametersEditor.queryByHook("parameters-list-container")) + let domainSection = $(this.parent.modelView.domainViewer.queryByHook("domain-container")) if(!domainSection.hasClass("show")) { - let domainCollapseBtn = $(this.parent.domainViewer.queryByHook("collapse")) + let domainCollapseBtn = $(this.parent.modelView.domainViewer.queryByHook("collapse")) domainCollapseBtn.click() domainCollapseBtn.html('-') } }, openParametersSection: function () { - let paramSection = $(this.parent.parametersEditor.queryByHook("parameters-list-container")) + let paramSection = $(this.parent.modelView.parametersView.queryByHook("parameters-list-container")) if(!paramSection.hasClass("show")) { - let paramCollapseBtn = $(this.parent.parametersEditor.queryByHook("collapse")) + let paramCollapseBtn = $(this.parent.modelView.parametersView.queryByHook("collapse")) paramCollapseBtn.click() paramCollapseBtn.html('-') } }, openReactionsSection: function (isCollection = false) { let error = this.model.error - let reacSection = $(this.parent.reactionsEditor.queryByHook("reactions-list-container")) + let reacSection = $(this.parent.modelView.reactionsView.queryByHook("reactions-list-container")) if(!reacSection.hasClass("show")) { - let reacCollapseBtn = $(this.parent.reactionsEditor.queryByHook("collapse")) + let reacCollapseBtn = $(this.parent.modelView.reactionsView.queryByHook("collapse")) reacCollapseBtn.click() reacCollapseBtn.html('-') } @@ -334,15 +394,15 @@ module.exports = View.extend({ }, openEventsSection: function () { let error = this.model.error - let advSection = $(this.parent.queryByHook("me-advanced-section")) + let advSection = $(this.parent.modelView.queryByHook("mv-advanced-section")) if(!advSection.hasClass("show")) { - let advCollapseBtn = $(this.parent.queryByHook("collapse-me-advanced-section")) + let advCollapseBtn = $(this.parent.modelView.queryByHook("collapse-mv-advanced-section")) advCollapseBtn.click() advCollapseBtn.html('-') } - let evtSection = $(this.eventsEditor.queryByHook("events")) + let evtSection = $(this.parent.modelView.eventsView.queryByHook("events")) if(!evtSection.hasClass("show")) { - let evtCollapseBtn = $(this.parent.eventsEditor.queryByHook("collapse")) + let evtCollapseBtn = $(this.parent.modelView.eventsView.queryByHook("collapse")) evtCollapseBtn.click() evtCollapseBtn.html('-') } @@ -359,9 +419,9 @@ module.exports = View.extend({ advCollapseBtn.click() advCollapseBtn.html('-') } - let ruleSection = $(this.rulesEditor.queryByHook("rules-list-container")) + let ruleSection = $(this.parent.modelView.rulesView.queryByHook("rules-list-container")) if(!ruleSection.hasClass("show")) { - let ruleCollapseBtn = $(this.parent.rulesEditor.queryByHook("collapse")) + let ruleCollapseBtn = $(this.parent.modelView.rulesView.queryByHook("collapse")) ruleCollapseBtn.click() ruleCollapseBtn.html('-') } diff --git a/client/views/model-viewer.js b/client/views/model-viewer.js deleted file mode 100644 index c1919f2440..0000000000 --- a/client/views/model-viewer.js +++ /dev/null @@ -1,96 +0,0 @@ -/* -StochSS is a platform for simulating biochemical systems -Copyright (C) 2019-2021 StochSS developers. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -//support files -let app = require('../app'); -//views -let View = require('ampersand-view'); -let EventsViewer = require('./events-editor'); -let RulesViewer = require('./rules-editor'); -let SpeciesViewer = require('./species-editor'); -let ReactionsViewer = require('./reactions-editor'); -let ParametersViewer = require('./parameters-editor'); -let SBMLComponentsView = require('./sbml-component-editor'); -//templates -let template = require('../templates/includes/modelViewer.pug'); - -module.exports = View.extend({ - template: template, - events: { - 'click [data-hook=collapse-model]' : 'changeCollapseButtonText' - }, - initialize: function (attrs, options) { - View.prototype.initialize.apply(this, arguments); - }, - render: function () { - View.prototype.render.apply(this, arguments); - this.renderSpeciesView(); - this.renderParametersView(); - this.renderReactionsView(); - this.renderEventsView(); - this.renderRulesView(); - this.renderSBMLComponentsView(); - }, - renderEventsView: function () { - let eventsViewer = new EventsViewer({ - collection: this.model.eventsCollection, - readOnly: true - }); - app.registerRenderSubview(this, eventsViewer, "events-viewer-container"); - }, - renderParametersView: function () { - let parametersViewer = new ParametersViewer({ - collection: this.model.parameters, - readOnly: true - }); - app.registerRenderSubview(this, parametersViewer, "parameters-viewer-container"); - }, - renderReactionsView: function () { - let reactionsViewer = new ReactionsViewer({ - collection: this.model.reactions, - readOnly: true - }); - app.registerRenderSubview(this, reactionsViewer, "reactions-viewer-container"); - }, - renderRulesView: function () { - let rulesViewer = new RulesViewer({ - collection: this.model.rules, - readOnly: true - }); - app.registerRenderSubview(this, rulesViewer, "rules-viewer-container"); - }, - renderSBMLComponentsView: function () { - let sbmlComponentsView = new SBMLComponentsView({ - functionDefinitions: this.model.functionDefinitions, - readOnly: true - }); - app.registerRenderSubview(this, sbmlComponentsView, "sbml-components-viewer-container"); - }, - renderSpeciesView: function () { - let speciesViewer = new SpeciesViewer({ - collection: this.model.species, - spatial: this.model.is_spatial, - defaultMode: this.model.defaultMode, - readOnly: true - }); - app.registerRenderSubview(this, speciesViewer, "species-viewer-container"); - }, - changeCollapseButtonText: function (e) { - app.changeCollapseButtonText(this, e); - } -}); diff --git a/client/views/settings-viewer.js b/client/views/settings-viewer.js index bb45c043a6..77d01c849f 100644 --- a/client/views/settings-viewer.js +++ b/client/views/settings-viewer.js @@ -37,9 +37,13 @@ module.exports = View.extend({ this.algorithm = this.model.simulationSettings.isAutomatic ? "The algorithm was chosen based on your model." : this.model.simulationSettings.algorithm + this.mode = Boolean(attrs.mode) ? attrs.mode : "edit"; }, render: function (attrs, options) { View.prototype.render.apply(this, arguments); + if(this.mode === "presentation") { + $(this.queryByHook("job-settings-header")).html("Settings") + } if(!this.parent.model.newFormat) { $(this.queryByHook("timespan-settings-viewer-container")).css("display", "none"); } diff --git a/client/views/workflow-results.js b/client/views/workflow-results.js index b0a9d8a153..95dc9fba28 100644 --- a/client/views/workflow-results.js +++ b/client/views/workflow-results.js @@ -20,6 +20,7 @@ let $ = require('jquery'); let path = require('path'); //support files let app = require('../app'); +let modals = require('../modals'); let Tooltips = require('../tooltips'); let Plotly = require('../lib/plotly'); //views @@ -49,13 +50,15 @@ module.exports = View.extend({ 'click [data-target=download-png-custom]' : 'handleDownloadPNGClick', 'click [data-target=download-json]' : 'handleDownloadJSONClick', 'click [data-hook=convert-to-notebook]' : 'handleConvertToNotebookClick', - 'click [data-hook=download-results-csv]' : 'handleDownloadResultsCsvClick' + 'click [data-hook=download-results-csv]' : 'handleDownloadResultsCsvClick', + // 'click [data-hook=job-presentation]' : 'handlePresentationClick' }, initialize: function (attrs, options) { View.prototype.initialize.apply(this, arguments); this.tooltips = Tooltips.parameterSweepResults; this.plots = {}; this.plotArgs = {}; + this.mode = Boolean(attrs.mode) ? attrs.mode : "edit"; }, render: function (attrs, options) { let isEnsemble = this.model.settings.simulationSettings.realizations > 1 && @@ -67,6 +70,16 @@ module.exports = View.extend({ this.template = isEnsemble ? gillespyResultsEnsembleTemplate : gillespyResultsTemplate; } View.prototype.render.apply(this, arguments); + if(this.mode === "presentation") { + $(this.queryByHook("job-presentation")).css("display", "none"); + if(!isParameterScan){ + $(this.queryByHook("convert-to-notebook")).css("display", "none"); + } + }else if(app.getBasePath() === "/") { + $(this.queryByHook("job-presentation")).css("display", "none"); + }else{ + $(this.queryByHook("job-presentation")).prop("disabled", true); + } if(this.parent.model.type === "Ensemble Simulation") { var type = isEnsemble ? "stddevran" : "trajectories"; }else{ @@ -96,6 +109,22 @@ module.exports = View.extend({ changeCollapseButtonText: function (e) { app.changeCollapseButtonText(this, e); }, + endAction: function () { + $(this.queryByHook("job-action-start")).css("display", "none"); + let saved = $(this.queryByHook("job-action-end")); + saved.css("display", "inline-block"); + setTimeout(function () { + saved.css("display", "none"); + }, 5000); + }, + errorAction: function () { + $(this.queryByHook("job-action-start")).css("display", "none"); + let error = $(this.queryByHook("job-action-err")); + error.css("display", "inline-block"); + setTimeout(function () { + error.css("display", "none"); + }, 5000); + }, cleanupPlotContainer: function (type) { let el = this.queryByHook(type + "-plot"); Plotly.purge(el); @@ -256,6 +285,22 @@ module.exports = View.extend({ } }); }, + handlePresentationClick: function (e) { + let self = this; + this.startAction(); + let name = this.parent.model.name + "_" + this.model.name; + let queryStr = "?path=" + this.model.directory + "&name=" + name; + let endpoint = path.join(app.getApiPath(), "job/presentation") + queryStr; + app.getXHR(endpoint, { + success: function (err, response, body) { + self.endAction(); + }, + error: function (err, response, body) { + self.errorAction(); + $(modals.newProjectModelErrorHtml(body.Reason, body.Message)).modal(); + } + }); + }, openPlotArgsSection: function (e) { $(this.queryByHook("edit-plot-args")).collapse("show"); $(document).ready(function () { @@ -376,6 +421,11 @@ module.exports = View.extend({ this.plotFigure(fig, type) } }, + startAction: function () { + $(this.queryByHook("job-action-start")).css("display", "inline-block"); + $(this.queryByHook("job-action-end")).css("display", "none"); + $(this.queryByHook("job-action-err")).css("display", "none"); + }, update: function () {}, updateValid: function () {}, subviews: { diff --git a/jupyter_notebook_config.py b/jupyter_notebook_config.py index 66b8ea4bad..4fc197c473 100644 --- a/jupyter_notebook_config.py +++ b/jupyter_notebook_config.py @@ -53,6 +53,8 @@ ## The default URL to redirect to from `/` c.NotebookApp.default_url = '/stochss/home' +c.NotebookApp.allow_remote_access = True + #------------------------------------------------------------------------------ # KernelManager(ConnectionFileMixin) configuration #------------------------------------------------------------------------------ @@ -182,4 +184,3 @@ ## This class manages the configuration. It's its own singleton class so that we # can share these values across all objects. It also contains some helper methods # to build request arguments out of the various config options. - diff --git a/jupyterhub/Dockerfile.jupyterhub b/jupyterhub/Dockerfile.jupyterhub index ab0119b137..eed510b44b 100644 --- a/jupyterhub/Dockerfile.jupyterhub +++ b/jupyterhub/Dockerfile.jupyterhub @@ -39,7 +39,9 @@ RUN python3 -m pip install --no-cache-dir \ jupyterhub==1.1.0 \ oauthenticator==0.11.* \ dockerspawner==0.11.* \ - psycopg2==2.7.* + psycopg2==2.7.* \ + nbviewer==1.0.1 \ + notebook COPY static/* /usr/local/share/jupyterhub/static/ diff --git a/jupyterhub/handlers.py b/jupyterhub/handlers.py index cd74cfb679..d891ed670f 100644 --- a/jupyterhub/handlers.py +++ b/jupyterhub/handlers.py @@ -1,7 +1,88 @@ +''' +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + from jupyterhub.handlers.base import BaseHandler +# pylint: disable=abstract-method +# pylint: disable=too-few-public-methods class HomeHandler(BaseHandler): + ''' + ################################################################################################ + Handler for rendering jupyterhub home page. + ################################################################################################ + ''' + async def get(self): + ''' + Render the jupyterhub home page. + + Attributes + ---------- + ''' + html = self.render_template("stochss-home.html") + self.finish(html) + + +class JobPresentationHandler(BaseHandler): + ''' + ################################################################################################ + Handler for rendering jupyterhub job presentation page. + ################################################################################################ + ''' + async def get(self): + ''' + Render the jupyterhub job presentation page. + + Attributes + ---------- + ''' + html = self.render_template("stochss-job-presentation.html") + self.finish(html) + + +class ModelPresentationHandler(BaseHandler): + ''' + ################################################################################################ + Handler for rendering jupyterhub model presentation page. + ################################################################################################ + ''' + async def get(self): + ''' + Render the jupyterhub model presentation page. + + Attributes + ---------- + ''' + html = self.render_template("stochss-model-presentation.html") + self.finish(html) + + +class NotebookPresentationHandler(BaseHandler): + ''' + ################################################################################################ + Handler for rendering jupyterhub notebook presentation page. + ################################################################################################ + ''' + async def get(self): + ''' + Render the jupyterhub notebook presentation page. - async def get(self): - html = self.render_template("stochss-home.html") - self.finish(html) + Attributes + ---------- + ''' + html = self.render_template("stochss-notebook-presentation.html") + self.finish(html) diff --git a/jupyterhub/home_template.pug b/jupyterhub/home_template.pug index 8558e61851..334896fd28 100644 --- a/jupyterhub/home_template.pug +++ b/jupyterhub/home_template.pug @@ -5,6 +5,10 @@ html head meta(charset="UTF-8") link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.8/themes/default/style.min.css") + title StochSS: Stochastic Simulation Service + meta(name="viewport", content="width=device-width, initial-scale=1.0") + meta(name="description", content="") + meta(name="author", content="") body script(type="text/javascript", src=bundleUrl) script(type="text/javascript", src=commonBundleUrl) diff --git a/jupyterhub/jupyterhub_config.py b/jupyterhub/jupyterhub_config.py index 6b4103d270..091e9602ab 100644 --- a/jupyterhub/jupyterhub_config.py +++ b/jupyterhub/jupyterhub_config.py @@ -1,8 +1,8 @@ # Configuration file for jupyterhub. -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- # Application(SingletonConfigurable) configuration -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- ## This is an application. @@ -15,29 +15,41 @@ ## Set the log level by value or name. #c.Application.log_level = 30 -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- # JupyterHub(Application) configuration -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- +import os +import os.path +import sys +import logging -import sys, os, os.path, shutil, logging +sys.path.append('/srv/jupyterhub/') # pylint: disable=wrong-import-position + +# API Handlers +from model_presentation import JsonFileAPIHandler, DownModelPresentationAPIHandler +from notebook_presentation import NotebookAPIHandler, DownNotebookPresentationAPIHandler +# Page handlers +from handlers import ( + HomeHandler, JobPresentationHandler, ModelPresentationHandler, NotebookPresentationHandler +) ## Class for authenticating users. -# +# # This should be a subclass of :class:`jupyterhub.auth.Authenticator` -# +# # with an :meth:`authenticate` method that: -# +# # - is a coroutine (asyncio or tornado) # - returns username on success, None on failure # - takes two arguments: (handler, data), # where `handler` is the calling web.RequestHandler, # and `data` is the POST form data from the login page. -# +# # .. versionchanged:: 1.0 # authenticators may be registered via entry points, # e.g. `c.JupyterHub.authenticator_class = 'pam'` -# -# Currently installed: +# +# Currently installed: # - default: jupyterhub.auth.PAMAuthenticator # - dummy: jupyterhub.auth.DummyAuthenticator # - pam: jupyterhub.auth.PAMAuthenticator @@ -51,12 +63,12 @@ data_dir = os.environ.get('DATA_VOLUME_CONTAINER', '/data') c.JupyterHub.cookie_secret_file = os.path.join(data_dir, - 'jupyterhub_cookie_secret') + 'jupyterhub_cookie_secret') c.JupyterHub.db_url = 'postgresql://postgres:{password}@{host}/{db}'.format( - host=os.environ['POSTGRES_HOST'], - password=os.environ['POSTGRES_PASSWORD'], - db=os.environ['POSTGRES_DB'], + host=os.environ['POSTGRES_HOST'], + password=os.environ['POSTGRES_PASSWORD'], + db=os.environ['POSTGRES_DB'], ) ## An Application for starting a Multi-User Jupyter Notebook server. @@ -66,70 +78,76 @@ c.JupyterHub.log_level = 'DEBUG' ## The default URL for users when they arrive (e.g. when user directs to "/") -# +# # By default, redirects users to their own server. c.JupyterHub.default_url = '/stochss' -# Page handlers -from handlers import HomeHandler - # StochSS request handlers c.JupyterHub.extra_handlers = [ - (r"/stochss\/?", HomeHandler), + (r"/stochss\/?", HomeHandler), + (r"/stochss/present-job\/?", JobPresentationHandler), + (r"/stochss/present-model\/?", ModelPresentationHandler), + (r"/stochss/present-notebook\/?", NotebookPresentationHandler), + (r"/stochss/api/file/json-data\/?", JsonFileAPIHandler), + (r"/stochss/download_presentation/(\w+)/(.+)\/?", DownModelPresentationAPIHandler), + (r"/stochss/api/notebook/load\/?", NotebookAPIHandler), + (r"/stochss/notebook/download_presentation/(\w+)/(.+)\/?", + DownNotebookPresentationAPIHandler) ] ## Paths to search for jinja templates, before using the default templates. c.JupyterHub.template_paths = [ - '/srv/jupyterhub/templates' + '/srv/jupyterhub/templates' ] ## The class to use for spawning single-user servers. -# +# # Should be a subclass of :class:`jupyterhub.spawner.Spawner`. -# +# # .. versionchanged:: 1.0 # spawners may be registered via entry points, # e.g. `c.JupyterHub.spawner_class = 'localprocess'` -# -# Currently installed: +# +# Currently installed: # - default: jupyterhub.spawner.LocalProcessSpawner # - localprocess: jupyterhub.spawner.LocalProcessSpawner # - simple: jupyterhub.spawner.SimpleLocalProcessSpawner c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner' ## The ip address for the Hub process to *bind* to. -# +# # By default, the hub listens on localhost only. This address must be accessible # from the proxy and user servers. You may need to set this to a public ip or '' # for all interfaces if the proxy or user servers are in containers or on a # different host. -# +# # See `hub_connect_ip` for cases where the bind and connect address should # differ, or `hub_bind_url` for setting the full bind URL. c.JupyterHub.hub_ip = os.environ.get('DOCKER_HUB_IMAGE') ## The internal port for the Hub process. -# +# # This is the internal port of the hub itself. It should never be accessed # directly. See JupyterHub.port for the public port to use when accessing # jupyterhub. It is rare that this port should be set except in cases of port # conflict. -# +# # See also `hub_ip` for the ip and `hub_bind_url` for setting the full bind URL. c.JupyterHub.hub_port = 8080 ## Services managed by JupyterHub c.JupyterHub.services = [ - { - 'name': 'cull-idle', - 'admin': True, - 'command': [sys.executable, '/srv/jupyterhub/cull_idle_servers.py', '--timeout=28800'], - } + { + 'name': 'cull-idle', + 'admin': True, + 'command': [sys.executable, '/srv/jupyterhub/cull_idle_servers.py', + '--timeout=28800'], + } ] -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- # Dockerspawner configuration -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- c.DockerSpawner.image = os.environ['DOCKER_STOCHSS_IMAGE'] # JupyterHub requires a single-user instance of the Notebook server, so we @@ -137,8 +155,8 @@ # jupyter/docker-stacks *-notebook images as the Docker run command when # spawning containers. Optionally, you can override the Docker run command # using the DOCKER_SPAWN_CMD environment variable. -spawn_cmd = "start-singleuser.sh" -c.DockerSpawner.extra_create_kwargs.update({ 'command': spawn_cmd }) +SPAWN_CMD = "start-singleuser.sh" +c.DockerSpawner.extra_create_kwargs.update({ 'command': SPAWN_CMD }) # Connect containers to this Docker network network_name = os.environ['DOCKER_NETWORK_NAME'] c.DockerSpawner.use_internal_ip = True @@ -146,7 +164,7 @@ # Pass the network name as argument to spawned containers # Pass cpu limit as extra config since dockerspawner does not natively support it c.DockerSpawner.extra_host_config = { - 'network_mode': network_name, + 'network_mode': network_name, } # Explicitly set notebook directory because we'll be mounting a host volume to # it. Most jupyter/docker-stacks *-notebook images run the Notebook server as @@ -159,153 +177,172 @@ c.DockerSpawner.volumes = { 'jupyterhub-user-{username}': notebook_dir } # Set extra environment variables c.DockerSpawner.environment = { - 'JUPYTER_CONFIG_DIR': os.environ['JUPYTER_CONFIG_DIR'] + 'JUPYTER_CONFIG_DIR': os.environ['JUPYTER_CONFIG_DIR'] } # Remove containers once they are stopped c.DockerSpawner.remove_containers = True # For debugging arguments passed to spawned containers c.DockerSpawner.debug = True -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- # Spawner(LoggingConfigurable) configuration -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- def get_user_cpu_count_or_fail(): - log = logging.getLogger() - reserve_count = int(os.environ['RESERVED_CPUS']) - log.info("RESERVED_CPUS environment variable is set to {}".format(reserve_count)) - # Round up to an even number of reserved cpus - if reserve_count % 2 > 0: - log.warn("Increasing reserved cpu count by one so it's an even number. This helps allocate logical cpus to users more easily.") - reserve_count += 1 - total_cpus = os.cpu_count() - log.info("Total cpu count as reported by os.count: {}".format(total_cpus)) - if reserve_count >= total_cpus: - e_message = "RESERVED_CPUS environment cannot be greater than or equal to the number of cpus returned by os.cpu_count()" - log.error(e_message) - raise ValueError(e_message) - user_cpu_count = total_cpus - reserve_count - # If (num logical cpus) - (num reserved cpus) is odd, - # use one less logical cpu for allocating user cpus - if user_cpu_count % 2 > 0 and user_cpu_count > 1: - user_cpu_count -= 1 - c.StochSS.reserved_cpu_count = reserve_count - log.info('Using {} logical cpus for user containers...'.format(user_cpu_count)) - log.info('Reserving {} logical cpus for hub container and underlying OS'.format(reserve_count)) - return user_cpu_count + ''' + Get the user cpu count or raise error + ''' + log = logging.getLogger() + reserve_count = int(os.environ['RESERVED_CPUS']) + log.info("RESERVED_CPUS environment variable is set to %s", reserve_count) + # Round up to an even number of reserved cpus + if reserve_count % 2 > 0: + message = "Increasing reserved cpu count by one so it's an even number." + message += " This helps allocate logical cpus to users more easily." + log.warning(message) + reserve_count += 1 + total_cpus = os.cpu_count() + log.info("Total cpu count as reported by os.count: %s", total_cpus) + if reserve_count >= total_cpus: + e_message = "RESERVED_CPUS environment cannot be greater than or equal to the number of" + e_message += " cpus returned by os.cpu_count()" + log.error(e_message) + raise ValueError(e_message) + user_cpu_count = total_cpus - reserve_count + # If (num logical cpus) - (num reserved cpus) is odd, + # use one less logical cpu for allocating user cpus + if user_cpu_count % 2 > 0 and user_cpu_count > 1: + user_cpu_count -= 1 + c.StochSS.reserved_cpu_count = reserve_count + log.info('Using %s logical cpus for user containers...', user_cpu_count) + log.info('Reserving %s logical cpus for hub container and underlying OS', reserve_count) + return user_cpu_count c.StochSS.user_cpu_count = get_user_cpu_count_or_fail() c.StochSS.user_cpu_alloc = [0] * c.StochSS.user_cpu_count def get_power_users(): - power_users_file = os.environ.get('POWER_USERS_FILE') - log = logging.getLogger() - if not os.path.exists(power_users_file): - log.warn('No power users defined!') - return [] - with open(power_users_file) as f: - power_users = [ x.rstrip() for x in f.readlines() ] - return power_users + ''' + Get the list of power users + ''' + power_users_file = os.environ.get('POWER_USERS_FILE') + log = logging.getLogger() + if not os.path.exists(power_users_file): + log.warning('No power users defined!') + return [] + with open(power_users_file) as file: + power_users = [ x.rstrip() for x in file.readlines() ] + return power_users c.StochSS.power_users = get_power_users() def pre_spawn_hook(spawner): - '''Function that runs before DockerSpawner spawns a user container. - Limits the resources available to user containers, excluding a list of power users. - ''' - log = logging.getLogger() - # Remove the memory limit for power users - if spawner.user.name in c.StochSS.power_users: - spawner.mem_limit = None - return - palloc = c.StochSS.user_cpu_alloc - div = len(palloc) // 2 - reserved = c.StochSS.reserved_cpu_count - log.warn('Reserved CPUs: {}'.format(reserved)) - log.warn('Number of user containers using each logical core: {}'.format(palloc)) - # We want to allocate logical cores that are on the same physical core - # whenever possible. - # - # A hyper-threaded 4-core processor has 8 logical cpus, with - # two logical cpus per core. Logical cpus on the same cpu core are grouped - # such that if (#, #) represents two logical cpus on a single physical core, - # then the logical cores in this case are indexed on the system like this: - # - # (1, 5), (2, 6), (3, 7), (4, 8) - # - # To allocate two logical cpus per user container, we find the logical cpu that - # is being used by the least number of users in the first half of an - # array tracking which users are using what logical cores. - # - # The general formula for finding the index of the second logical core - # on the same physical core is then: - # - # index(matching logical core) = - # index(chosen logical core) + ( (number of logical cores) / 2 ) - # - avail_cpus = palloc[div:] - # If <= 4 cpus available then use 1 cpu for each user instead of 2 - if not len(avail_cpus): - log.warn("The host system only has 4 logical cpus, so we'll only reserve one logical cpu per user container, instead of the normal 2") - avail_cpus = palloc - least_used_cpu = min(avail_cpus) - cpu1_index = avail_cpus.index(least_used_cpu) - log.info("User {} to use logical cpu {}".format(spawner.user.name, str(cpu1_index))) - palloc[cpu1_index] += 1 - spawner.extra_host_config['cpuset_cpus'] = '{}'.format(cpu1_index) - else: - least_used_cpu = min(avail_cpus) - cpu1_index = avail_cpus.index(least_used_cpu) - palloc[cpu1_index] += 1 - cpu2_index = cpu1_index+div - palloc[cpu2_index] += 1 - log.info("User {} to use logical cpus {} and {}".format( - spawner.user.name, str(cpu1_index), str(cpu2_index))) - spawner.extra_host_config['cpuset_cpus'] = '{},{}'.format(cpu1_index, cpu2_index) + ''' + Function that runs before DockerSpawner spawns a user container. + Limits the resources available to user containers, excluding a list of power users. + ''' + log = logging.getLogger() + # Remove the memory limit for power users + if spawner.user.name in c.StochSS.power_users: + spawner.mem_limit = None + return + palloc = c.StochSS.user_cpu_alloc + div = len(palloc) // 2 + reserved = c.StochSS.reserved_cpu_count + log.warning('Reserved CPUs: %s', reserved) + log.warning('Number of user containers using each logical core: %s', palloc) + # We want to allocate logical cores that are on the same physical core + # whenever possible. + # + # A hyper-threaded 4-core processor has 8 logical cpus, with + # two logical cpus per core. Logical cpus on the same cpu core are grouped + # such that if (#, #) represents two logical cpus on a single physical core, + # then the logical cores in this case are indexed on the system like this: + # + # (1, 5), (2, 6), (3, 7), (4, 8) + # + # To allocate two logical cpus per user container, we find the logical cpu that + # is being used by the least number of users in the first half of an + # array tracking which users are using what logical cores. + # + # The general formula for finding the index of the second logical core + # on the same physical core is then: + # + # index(matching logical core) = + # index(chosen logical core) + ( (number of logical cores) / 2 ) + # + avail_cpus = palloc[div:] + # If <= 4 cpus available then use 1 cpu for each user instead of 2 + if not avail_cpus: + message = "The host system only has 4 logical cpus, so we'll only reserve" + message += " one logical cpu per user container, instead of the normal 2" + log.warning(message) + avail_cpus = palloc + least_used_cpu = min(avail_cpus) + cpu1_index = avail_cpus.index(least_used_cpu) + log.info("User %s to use logical cpu %s", spawner.user.name, str(cpu1_index)) + palloc[cpu1_index] += 1 + spawner.extra_host_config['cpuset_cpus'] = '{}'.format(cpu1_index) + else: + least_used_cpu = min(avail_cpus) + cpu1_index = avail_cpus.index(least_used_cpu) + palloc[cpu1_index] += 1 + cpu2_index = cpu1_index+div + palloc[cpu2_index] += 1 + log.info("User %s to use logical cpus %s and %s", + spawner.user.name, str(cpu1_index), str(cpu2_index)) + spawner.extra_host_config['cpuset_cpus'] = '{},{}'.format(cpu1_index, cpu2_index) def post_stop_hook(spawner): - log = logging.getLogger() - reserved = c.StochSS.reserved_cpu_count - palloc = c.StochSS.user_cpu_alloc - try: - cpu1_index, cpu2_index = spawner.extra_host_config['cpuset_cpus'].split(',') - palloc[int(cpu1_index)] -= 1 - palloc[int(cpu2_index)] -= 1 - log.warn('Reserved CPUs: {}'.format(reserved)) - log.warn('Number of user containers using each logical core: {}'.format(palloc)) - except: - # Exception thrown due to cpuset_cpus not being set (power user) - pass + ''' + Post stop hook + ''' + log = logging.getLogger() + reserved = c.StochSS.reserved_cpu_count + palloc = c.StochSS.user_cpu_alloc + try: + cpu1_index, cpu2_index = spawner.extra_host_config['cpuset_cpus'].split(',') + palloc[int(cpu1_index)] -= 1 + palloc[int(cpu2_index)] -= 1 + log.warning('Reserved CPUs: %s', reserved) + log.warning('Number of user containers using each logical core: %s', palloc) + except Exception as err: + message = "Exception thrown due to cpuset_cpus not being set (power user)" + log.error("%s\n%s", message, err) + # Exception thrown due to cpuset_cpus not being set (power user) + pass c.Spawner.pre_spawn_hook = pre_spawn_hook c.Spawner.post_stop_hook = post_stop_hook ## The URL the single-user server should start in. -# +# # `{username}` will be expanded to the user's username -# +# # Example uses: -# -# - You can set `notebook_dir` to `/` and `default_url` to `/tree/home/{username}` to allow people to -# navigate the whole filesystem from their notebook server, but still start in their home directory. -# - Start with `/notebooks` instead of `/tree` if `default_url` points to a notebook instead of a directory. +# +# - You can set `notebook_dir` to `/` and `default_url` to `/tree/home/{username}` to allow people +# to navigate the whole filesystem from their notebook server, but still start in their home +# directory. +# - Start with `/notebooks` instead of `/tree` if `default_url` points to a notebook instead of a +# directory. # - You can set this to `/lab` to have JupyterLab start by default, rather than Jupyter Notebook. c.Spawner.default_url = '/stochss/models' ## Maximum number of bytes a single-user notebook server is allowed to use. -# +# # Allows the following suffixes: # - K -> Kilobytes # - M -> Megabytes # - G -> Gigabytes # - T -> Terabytes -# +# # If the single user server tries to allocate more memory than this, it will # fail. There is no guarantee that the single-user notebook server will be able # to allocate this much memory - only that it can not allocate more than this. -# +# # **This is a configuration setting. Your spawner must implement support for the # limit to work.** The default spawner, `LocalProcessSpawner`, does **not** # implement this support. A custom spawner **must** add support for this setting @@ -313,14 +350,14 @@ def post_stop_hook(spawner): c.Spawner.mem_limit = '4G' ## Maximum number of cpu-cores a single-user notebook server is allowed to use. -# +# # If this value is set to 0.5, allows use of 50% of one CPU. If this value is # set to 2, allows use of up to 2 CPUs. -# +# # The single-user notebook server will never be scheduled by the kernel to use # more cpu-cores than this. There is no guarantee that it can access this many # cpu-cores. -# +# # **This is a configuration setting. Your spawner must implement support for the # limit to work.** The default spawner, `LocalProcessSpawner`, does **not** # implement this support. A custom spawner **must** add support for this setting @@ -328,20 +365,20 @@ def post_stop_hook(spawner): #c.Spawner.cpu_limit = 2 ## Extra arguments to be passed to the single-user server. -# +# # Some spawners allow shell-style expansion here, allowing you to use # environment variables here. Most, including the default, do not. Consult the # documentation for your spawner to verify! #c.Spawner.args = [] ## The command used for starting the single-user server. -# +# # Provide either a string or a list containing the path to the startup script # command. Extra arguments, other than this path, should be provided via `args`. -# +# # This is usually set if you want to start the single-user server in a different # python environment (with virtualenv/conda) than JupyterHub itself. -# +# # Some spawners allow shell-style expansion here, allowing you to use # environment variables. Most, including the default, do not. Consult the # documentation for your spawner to verify! @@ -349,10 +386,10 @@ def post_stop_hook(spawner): ## Minimum number of cpu-cores a single-user notebook server is guaranteed to # have available. -# +# # If this value is set to 0.5, allows use of 50% of one CPU. If this value is # set to 2, allows use of up to 2 CPUs. -# +# # **This is a configuration setting. Your spawner must implement support for the # limit to work.** The default spawner, `LocalProcessSpawner`, does **not** # implement this support. A custom spawner **must** add support for this setting @@ -362,48 +399,48 @@ def post_stop_hook(spawner): ## Minimum number of bytes a single-user notebook server is guaranteed to have # available. -# +# # Allows the following suffixes: # - K -> Kilobytes # - M -> Megabytes # - G -> Gigabytes # - T -> Terabytes -# +# # **This is a configuration setting. Your spawner must implement support for the # limit to work.** The default spawner, `LocalProcessSpawner`, does **not** # implement this support. A custom spawner **must** add support for this setting # for it to be enforced. c.Spawner.mem_guarantee = '2G' -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- # Authenticator(LoggingConfigurable) configuration -#------------------------------------------------------------------------------ +#--------------------------------------------------------------------------------------------------- ## Base class for implementing an authentication provider for JupyterHub ## Set of users that will have admin rights on this JupyterHub. -# +# # Admin users have extra privileges: # - Use the admin panel to see list of users logged in # - Add / remove users in some authenticators # - Restart / halt the hub # - Start / stop users' single-user servers # - Can access each individual users' single-user server (if configured) -# +# # Admin access should be treated the same way root access is. -# +# # Defaults to an empty set, in which case no user has admin access. c.Authenticator.admin_users = admin = set([]) pwd = os.path.dirname(__file__) with open(os.path.join(pwd, 'userlist')) as f: - for line in f: - if not line: - continue - parts = line.split() - # in case of newline at the end of userlist file - if len(parts) >= 1: - name = parts[0] - #whitelist.add(name) - if len(parts) > 1 and parts[1] == 'admin': - admin.add(name) + for line in f: + if not line: + continue + parts = line.split() + # in case of newline at the end of userlist file + if len(parts) >= 1: + name = parts[0] + #whitelist.add(name) + if len(parts) > 1 and parts[1] == 'admin': + admin.add(name) diff --git a/jupyterhub/model_presentation.py b/jupyterhub/model_presentation.py new file mode 100644 index 0000000000..2467333363 --- /dev/null +++ b/jupyterhub/model_presentation.py @@ -0,0 +1,258 @@ +''' +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + +import ast +import json +import logging + +from presentation_base import StochSSBase, get_presentation_from_user +from presentation_error import StochSSAPIError, report_error + +from jupyterhub.handlers.base import BaseHandler + +log = logging.getLogger('stochss') + +# pylint: disable=abstract-method +# pylint: disable=too-few-public-methods +class JsonFileAPIHandler(BaseHandler): + ''' + ################################################################################################ + Base Handler for getting model presentations from user containers. + ################################################################################################ + ''' + async def get(self): + ''' + Load the model presentation from User's presentations directory. + + Attributes + ---------- + ''' + owner = self.get_query_argument(name="owner") + log.debug("Container id of the owner: %s", owner) + file = self.get_query_argument(name="file") + log.debug("Name to the file: %s", file) + self.set_header('Content-Type', 'application/json') + try: + model = get_presentation_from_user(owner=owner, file=file, kwargs={"file": file}, + process_func=process_model_presentation) + log.debug("Contents of the json file: %s", model) + self.write(model) + except StochSSAPIError as load_err: + report_error(self, log, load_err) + self.finish() + + +class DownModelPresentationAPIHandler(BaseHandler): + ''' + ################################################################################################ + Base Handler for downloading model presentations from user containers. + ################################################################################################ + ''' + async def get(self, owner, file): + ''' + Download the model presentation from User's presentations directory. + + Attributes + ---------- + ''' + log.debug("Container id of the owner: %s", owner) + log.debug("Name to the file: %s", file) + self.set_header('Content-Type', 'application/json') + model = get_presentation_from_user(owner=owner, file=file, + kwargs={"for_download": True}, + process_func=process_model_presentation) + ext = file.split(".").pop() + self.set_header('Content-Disposition', f'attachment; filename="{model["name"]}.{ext}"') + log.debug("Contents of the json file: %s", model) + self.write(model) + self.finish() + + +def process_model_presentation(path, file=None, for_download=False): + ''' + Get the model presentation data from the file. + + Attributes + ---------- + path : str + Path to the model presentation file. + file : str + Name of the presentation file. + for_download : bool + Whether or not the model presentation is being downloaded. + ''' + with open(path, "r") as mdl_file: + model = json.load(mdl_file) + if for_download: + return model + file_objs = {"mdl":StochSSModel, "smdl":StochSSSpatialModel} + ext = file.split(".").pop() + file_obj = file_objs[ext](model=model) + model_pres = file_obj.load() + file_obj.print_logs(log) + return model_pres + + +class StochSSModel(StochSSBase): + ''' + ################################################################################################ + StochSS model object + ################################################################################################ + ''' + + def __init__(self, model): + ''' + Intitialize a model object + + Attributes + ---------- + model : dict + Existing model data + ''' + super().__init__() + self.model = model + + + @classmethod + def __update_event_assignments(cls, event, param_ids): + if "eventAssignments" not in event.keys(): + return + for assignment in event['eventAssignments']: + try: + if assignment['variable']['compID'] in param_ids: + expression = ast.literal_eval(assignment['variable']['expression']) + assignment['variable']['expression'] = expression + except KeyError: + pass + except ValueError: + pass + + + def __update_events(self, param_ids): + if "eventsCollection" not in self.model.keys() or not param_ids: + return + for event in self.model['eventsCollection']: + self.__update_event_assignments(event=event, param_ids=param_ids) + + + def __update_parameters(self): + if "parameters" not in self.model.keys(): + return [] + param_ids = [] + for param in self.model['parameters']: + try: + param_ids.append(param['compID']) + if isinstance(param['expression'], str): + param['expression'] = ast.literal_eval(param['expression']) + except KeyError: + pass + except ValueError: + pass + return param_ids + + + def __update_reactions(self): + if "reactions" not in self.model.keys(): + return + for reaction in self.model['reactions']: + try: + if reaction['rate'].keys() and isinstance(reaction['rate']['expression'], str): + expression = ast.literal_eval(reaction['rate']['expression']) + reaction['rate']['expression'] = expression + except KeyError: + pass + except ValueError: + pass + + + def __update_rules(self, param_ids): + if "rules" not in self.model.keys() or not param_ids: + return + for rule in self.model['rules']: + try: + if rule['variable']['compID'] in param_ids: + expression = ast.literal_eval(rule['variable']['expression']) + rule['variable']['expression'] = expression + except KeyError: + pass + except ValueError: + pass + + + def load(self): + ''' + Reads the model file, updates the model to the current format, and stores it in self.model + + Attributes + ---------- + ''' + if "annotation" not in self.model.keys(): + self.model['annotation'] = "" + if "volume" not in self.model.keys(): + if "volume" in self.model['modelSettings'].keys(): + self.model['volume'] = self.model['modelSettings']['volume'] + else: + self.model['volume'] = 1 + param_ids = self.__update_parameters() + self.__update_reactions() + self.__update_events(param_ids=param_ids) + self.__update_rules(param_ids=param_ids) + return self.model + + +class StochSSSpatialModel(StochSSBase): + ''' + ################################################################################################ + StochSS spatial model object + ################################################################################################ + ''' + + def __init__(self, model): + ''' + Intitialize a spatial model object + + Attributes + ---------- + model : dict + Existing model data + ''' + super().__init__() + self.model = model + + + def load(self): + ''' + Reads the spatial model file, updates it to the current format, and stores it in self.model + + Attributes + ---------- + ''' + if not self.model['defaultMode']: + self.model['defaultMode'] = "discrete" + if "static" not in self.model['domain'].keys(): + self.model['domain']['static'] = True + for species in self.model['species']: + if "types" not in species.keys(): + species['types'] = list(range(1, len(self.model['domain']['types']))) + if "diffusionConst" not in species.keys(): + diff = 0.0 if "diffusionCoeff" not in species.keys() else species['diffusionCoeff'] + species['diffusionConst'] = diff + for reaction in self.model['reactions']: + if "types" not in reaction.keys(): + reaction['types'] = list(range(1, len(self.model['domain']['types']))) + return self.model diff --git a/jupyterhub/notebook_presentation.py b/jupyterhub/notebook_presentation.py new file mode 100644 index 0000000000..4482b4ed12 --- /dev/null +++ b/jupyterhub/notebook_presentation.py @@ -0,0 +1,101 @@ +''' +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + +import json +import logging +import nbformat + +from nbviewer.render import render_notebook +from nbconvert.exporters import HTMLExporter + +from presentation_base import get_presentation_from_user + +from jupyterhub.handlers.base import BaseHandler + +log = logging.getLogger('stochss') + +# pylint: disable=abstract-method +# pylint: disable=too-few-public-methods +class NotebookAPIHandler(BaseHandler): + ''' + ################################################################################################ + Base Handler for getting notebook presentations from user containers. + ################################################################################################ + ''' + async def get(self): + ''' + Load the notebook presentation from User's presentations directory. + + Attributes + ---------- + ''' + self.set_header('Content-Type', 'application/json') + owner = self.get_query_argument(name="owner") + log.debug("Container id of the owner: %s", owner) + file = self.get_query_argument(name="file") + log.debug("Name to the file: %s", file) + html = get_presentation_from_user(owner=owner, file=file, + process_func=process_notebook_presentation) + self.write(html) + self.finish() + + +class DownNotebookPresentationAPIHandler(BaseHandler): + ''' + ################################################################################################ + Base Handler for downloading notebook presentations from user containers. + ################################################################################################ + ''' + async def get(self, owner, file): + ''' + Download the notebook presentation from User's presentations directory. + + Attributes + ---------- + ''' + log.debug("Container id of the owner: %s", owner) + log.debug("Name to the file: %s", file) + self.set_header('Content-Type', 'application/json') + nb_presentation = get_presentation_from_user(owner=owner, file=file, + kwargs={"as_dict": True}, + process_func=process_notebook_presentation) + self.set_header('Content-Disposition', f'attachment; filename="{nb_presentation["file"]}"') + log.debug("Contents of the json file: %s", nb_presentation['notebook']) + self.write(nb_presentation['notebook']) + self.finish() + + +def process_notebook_presentation(path, as_dict=False): + ''' + Get the notebook presentation data from the file. + + Attributes + ---------- + path : str + Path to the notebook presentation file + as_dict : bool + Whether or not to return the data as a dictionary + ''' + with open(path, "r") as nb_file: + nb_presentation = json.load(nb_file) + if as_dict: + return nb_presentation + notebook = nbformat.reads(json.dumps(nb_presentation['notebook']), as_version=4) + nb_format = {"exporter": HTMLExporter} + html, _ = render_notebook(format=nb_format, nb=notebook) + return {"file": nb_presentation['file'], "html": html} diff --git a/jupyterhub/presentation_base.py b/jupyterhub/presentation_base.py new file mode 100644 index 0000000000..421a9ed4b4 --- /dev/null +++ b/jupyterhub/presentation_base.py @@ -0,0 +1,126 @@ +''' +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + +import os +import tarfile +import tempfile + +import docker + + +def __get_presentation_from_volume(client, owner, file): + volumes = client.volumes.list() + user_volume = list(filter(lambda volume: volume.name == f"jupyterhub-user-{owner}", + volumes))[0] + volume_mnts = {user_volume.name: {"bind": "/user_volume", "mode": "ro"}, + "/stochss/jupyterhub": {"bind": "/mnt/cache", "mode": "rw"}} + command = ['cp', os.path.join('/user_volume/.presentations', file), + '/mnt/cache/presentation_cache/'] + client.containers.run('stochss-lab', command, volumes=volume_mnts) + file_path = os.path.join('/srv/jupyterhub/presentation_cache', file) + return file_path + + +def get_presentation_from_user(owner, file, process_func, kwargs=None): + ''' + Get the model presentation from the users container + + Attributes + ---------- + owner : str + Hostname of the user container + file : str + Name of the model presentation file + process_func : function + Function used to process the presentation file + kwargs : dict + Args to be passed to the process function + ''' + client = docker.from_env() + containers = client.containers.list() + try: + user_container = list(filter(lambda container: container.name == f"jupyter-{owner}", + containers))[0] + except IndexError: + file_path = __get_presentation_from_volume(client, owner, file) + else: + user_file_path = os.path.join('/home/jovyan/.presentations', file) + tar_pres = tempfile.TemporaryFile() + bits, _ = user_container.get_archive(user_file_path) + for chunk in bits: + tar_pres.write(chunk) + tar_pres.seek(0) + tar_file = tarfile.TarFile(fileobj=tar_pres) + tmp_dir = tempfile.TemporaryDirectory() + tar_file.extractall(tmp_dir.name) + tar_pres.close() + file_path = os.path.join(tmp_dir.name, file) + if kwargs is None: + kwargs = {} + return process_func(file_path, **kwargs) + + +class StochSSBase(): + ''' + ################################################################################################ + StochSS base object + ################################################################################################ + ''' + user_dir = os.path.expanduser("~") # returns the path to the users home directory + + def __init__(self, path=None): + ''' + Intitialize a file object + + Attributes + ---------- + path : str + Path to the folder + ''' + self.path = path + self.logs = [] + + + def log(self, level, message): + ''' + Add a log to the objects internal logs + + Attribute + --------- + level : str + Level of the log + message : string + Message to be logged + ''' + self.logs.append({"level":level, "message":message}) + + + def print_logs(self, log): + ''' + Display all internal logs to the console + + Attributes + ---------- + log : obj + Logging object + ''' + displays = {"debug":log.debug, "info":log.info, "warning":log.warning, + "error":log.error, "critical":log.critical} + for entry in self.logs: + log_display = displays[entry["level"]] + log_display(entry["message"]) diff --git a/jupyterhub/presentation_error.py b/jupyterhub/presentation_error.py new file mode 100644 index 0000000000..79cfe04e07 --- /dev/null +++ b/jupyterhub/presentation_error.py @@ -0,0 +1,118 @@ +''' +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + +import traceback + +def report_error(handler, log, err): + ''' + Report a stochss error to the front end + + Attributes + ---------- + handler : obj + Jupyter Notebook API Handler + log : obj + StochSS log + ''' + handler.set_status(err.status_code) + error = {"Reason":err.reason, "Message":err.message} + if err.traceback is None: + trace = traceback.format_exc() + else: + trace = err.traceback + log.error("Exception information: %s\n%s", error, trace) + error['Traceback'] = trace + handler.write(error) + + +class StochSSAPIError(Exception): + ''' + ################################################################################################ + StochSS Base Api Handler Error + ################################################################################################ + ''' + + def __init__(self, status_code, reason, msg, trace): + ''' + Base error for all stochss api errors + + Attributes + ---------- + status_code : int + XML request status code + reason : str + Reason for the error + msg : str + Details on what caused the error + trace : str + Error traceback for the error + ''' + super().__init__() + self.status_code = status_code + self.reason = reason + self.message = msg + self.traceback = trace + + +#################################################################################################### +# File System Errors +#################################################################################################### + +class StochSSFileNotFoundError(StochSSAPIError): + ''' + ################################################################################################ + StochSS File/Folder Not Found API Handler Error + ################################################################################################ + ''' + + def __init__(self, msg, trace=None): + ''' + Indicates that the file/folder with the given path does not exist + + Attributes + ---------- + msg : str + Details on what caused the error + trace : str + Error traceback for the error + ''' + super().__init__(404, "StochSS File or Directory Not Found", msg, trace) + +#################################################################################################### +# Model Errors +#################################################################################################### + +class FileNotJSONFormatError(StochSSAPIError): + ''' + ################################################################################################ + StochSS Model/Template Not In JSON Format + ################################################################################################ + ''' + + def __init__(self, msg, trace=None): + ''' + Indicates that the model or template file is not in proper JSON format + + Attributes + ---------- + msg : str + Details on what caused the error + trace : str + Error traceback for the error + ''' + super().__init__(406, "File Data Not JSON Format", msg, trace) diff --git a/jupyterhub/templates/stochss-job-presentation.html b/jupyterhub/templates/stochss-job-presentation.html new file mode 100644 index 0000000000..47c4ea2ab8 --- /dev/null +++ b/jupyterhub/templates/stochss-job-presentation.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/jupyterhub/templates/stochss-model-presentation.html b/jupyterhub/templates/stochss-model-presentation.html new file mode 100644 index 0000000000..3092353528 --- /dev/null +++ b/jupyterhub/templates/stochss-model-presentation.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public_models/3D_Cylinder/3D_cylinder.smdl b/public_models/3D_Cylinder/3D_cylinder.smdl index 3eb1226d2e..87f03f038a 100644 --- a/public_models/3D_Cylinder/3D_cylinder.smdl +++ b/public_models/3D_Cylinder/3D_cylinder.smdl @@ -1 +1 @@ -{"annotation":"SpatialPy 3D Cylinder Demo Model","defaultID":9,"defaultMode":"discrete","domain":{"boundary_condition":{"reflect_x":true,"reflect_y":true,"reflect_z":true},"c_0":10,"gravity":[0, 0, 0],"p_0":10,"particles":[{"fixed":false,"mass":0.015135255135374578,"nu":0,"particle_id":1,"point":[-2.101682616989703,-0.964452787824742,0.2489313344981683],"type":1,"volume":0.015135255135374578},{"fixed":false,"mass":0.07034111605740352,"nu":0,"particle_id":2,"point":[-1.887513465434122,-0.5014916255865332,0.06961314329212905],"type":1,"volume":0.07034111605740352},{"fixed":false,"mass":0.02382667425447659,"nu":0,"particle_id":3,"point":[-1.757042722631912,-0.9228641348563182,0.3845831077631754],"type":1,"volume":0.02382667425447659},{"fixed":false,"mass":0.01837175522796916,"nu":0,"particle_id":4,"point":[-1.85413888369328,-0.9955594999585697,0.04508515352682077],"type":1,"volume":0.01837175522796916},{"fixed":false,"mass":0.04863919527628578,"nu":0,"particle_id":5,"point":[1.874975500982107,0.2492223157132696,-0.2524856754824046],"type":1,"volume":0.04863919527628578},{"fixed":false,"mass":0.0632175288192508,"nu":0,"particle_id":6,"point":[1.808320438516406,0.05711590686461099,-0.6164182499126918],"type":1,"volume":0.0632175288192508},{"fixed":false,"mass":0.05566341760973872,"nu":0,"particle_id":7,"point":[2.182529343210714,-0.1663114027612958,-0.4557993633541657],"type":1,"volume":0.05566341760973872},{"fixed":false,"mass":0.05094615682555442,"nu":0,"particle_id":8,"point":[2.06222242502517,-0.06584170406028653,-0.09390309609504216],"type":1,"volume":0.05094615682555442},{"fixed":false,"mass":0.027613011065781377,"nu":0,"particle_id":9,"point":[-2.380044639472586,0.1039603942187995,-0.6660021716554381],"type":1,"volume":0.027613011065781377},{"fixed":false,"mass":0.043631235211839,"nu":0,"particle_id":10,"point":[-2.305676947241498,-0.3113331410231057,-0.589095101307394],"type":1,"volume":0.043631235211839},{"fixed":false,"mass":0.02307565554258796,"nu":0,"particle_id":11,"point":[-2.262942990799641,-0.04111516086018868,-0.9959505101076245],"type":1,"volume":0.02307565554258796},{"fixed":false,"mass":0.053285055209458865,"nu":0,"particle_id":12,"point":[-2.093631369619373,-0.04820563757950643,-0.6060599358098253],"type":1,"volume":0.053285055209458865},{"fixed":false,"mass":0.013863453851301994,"nu":0,"particle_id":13,"point":[-1.999792859336622,-0.94943344706238,-0.2984434655811745],"type":1,"volume":0.013863453851301994},{"fixed":false,"mass":0.006452758616580852,"nu":0,"particle_id":14,"point":[-1.754728853599724,-0.8801338975074484,-0.464525759047439],"type":1,"volume":0.006452758616580852},{"fixed":false,"mass":0.06319118564277616,"nu":0,"particle_id":15,"point":[-1.689826608177531,-0.5981799589653591,-0.2304829208262158],"type":1,"volume":0.06319118564277616},{"fixed":false,"mass":0.012063450996053436,"nu":0,"particle_id":16,"point":[-1.670428874777768,-0.9736314258341583,-0.2186734200213536],"type":1,"volume":0.012063450996053436},{"fixed":false,"mass":0.06390075032081181,"nu":0,"particle_id":17,"point":[3.590501737794977,-0.4310110060573188,-0.3131780598352483],"type":1,"volume":0.06390075032081181},{"fixed":false,"mass":0.03900782913147994,"nu":0,"particle_id":18,"point":[3.257879943487412,-0.4243756833306612,0.07732536880979513],"type":1,"volume":0.03900782913147994},{"fixed":false,"mass":0.07191513330511291,"nu":0,"particle_id":19,"point":[3.160881489131067,-0.4731490872585901,-0.3414347939235592],"type":1,"volume":0.07191513330511291},{"fixed":false,"mass":0.03889328117454658,"nu":0,"particle_id":20,"point":[3.4964304507652,-0.6577183471508495,-0.05248579623331021],"type":1,"volume":0.03889328117454658},{"fixed":false,"mass":0.03917814937239849,"nu":0,"particle_id":21,"point":[-0.6913178542741429,0.2146395970789712,-0.1038293381612584],"type":1,"volume":0.03917814937239849},{"fixed":false,"mass":0.06467136826869545,"nu":0,"particle_id":22,"point":[-1.044361330579384,0.5974390889571882,-0.01981372633389583],"type":1,"volume":0.06467136826869545},{"fixed":false,"mass":0.03678980262339302,"nu":0,"particle_id":23,"point":[-0.8108570256428013,0.2125028850865174,0.2175561585244626],"type":1,"volume":0.03678980262339302},{"fixed":false,"mass":0.040413057773667674,"nu":0,"particle_id":24,"point":[-0.5850074823172771,0.433377778775099,0.1301490585358179],"type":1,"volume":0.040413057773667674},{"fixed":false,"mass":0.04369920752229525,"nu":0,"particle_id":25,"point":[-0.2936847104329262,0.4884589904276384,0.405308684893338],"type":1,"volume":0.04369920752229525},{"fixed":false,"mass":0.019707836516532865,"nu":0,"particle_id":26,"point":[0.06755331827299763,0.6967326601039996,0.7156206023324831],"type":1,"volume":0.019707836516532865},{"fixed":false,"mass":0.0229023521723117,"nu":0,"particle_id":27,"point":[-0.2711331659044802,0.6029126244346361,0.792616715761118],"type":1,"volume":0.0229023521723117},{"fixed":false,"mass":0.05884538686747711,"nu":0,"particle_id":28,"point":[0.01874290730254941,0.2368088283033387,0.4570474213646968],"type":1,"volume":0.05884538686747711},{"fixed":false,"mass":0.03421042879504796,"nu":0,"particle_id":29,"point":[4.43058544654569,0.6917465481935645,-0.1318762867133248],"type":1,"volume":0.03421042879504796},{"fixed":false,"mass":0.05344933653752932,"nu":0,"particle_id":30,"point":[4.508673766283515,0.4850515259508832,0.1265351969117867],"type":1,"volume":0.05344933653752932},{"fixed":false,"mass":0.0541141059782541,"nu":0,"particle_id":31,"point":[4.325610933271159,0.1837641403320487,-0.228199869286026],"type":1,"volume":0.0541141059782541},{"fixed":false,"mass":0.05523181637938297,"nu":0,"particle_id":32,"point":[4.611989612137674,0.4816263712555289,-0.3281902004283623],"type":1,"volume":0.05523181637938297},{"fixed":false,"mass":0.03254264921165492,"nu":0,"particle_id":33,"point":[3.433864759691629,-0.6320042529451704,0.2801340391076638],"type":1,"volume":0.03254264921165492},{"fixed":false,"mass":0.014880838966590903,"nu":0,"particle_id":34,"point":[3.488844898689435,-0.7730604064130339,0.6267420563227659],"type":1,"volume":0.014880838966590903},{"fixed":false,"mass":0.015892280530313798,"nu":0,"particle_id":35,"point":[3.289395677680728,-0.915443716604872,0.3984657338720717],"type":1,"volume":0.015892280530313798},{"fixed":false,"mass":0.017242446554284085,"nu":0,"particle_id":36,"point":[3.620442983847549,-0.9334678696573689,0.3510749208361043],"type":1,"volume":0.017242446554284085},{"fixed":false,"mass":0.017319408013948448,"nu":0,"particle_id":37,"point":[3.711388702989438,-0.9376186091765497,-0.3373917664009833],"type":1,"volume":0.017319408013948448},{"fixed":false,"mass":0.03942973229567603,"nu":0,"particle_id":38,"point":[3.857684954996952,-0.6324880361221572,-0.188173657943937],"type":1,"volume":0.03942973229567603},{"fixed":false,"mass":0.01060732084260641,"nu":0,"particle_id":39,"point":[3.974630202682578,-0.9645949697573137,-0.2484626234811865],"type":1,"volume":0.01060732084260641},{"fixed":false,"mass":0.018929906757140968,"nu":0,"particle_id":40,"point":[4.00385419870279,-0.8584909334426989,-0.5050168968536721],"type":1,"volume":0.018929906757140968},{"fixed":false,"mass":0.05111105459146263,"nu":0,"particle_id":41,"point":[-3.91324743689939,-0.02166296556491133,-0.5259588911325391],"type":1,"volume":0.05111105459146263},{"fixed":false,"mass":0.026733958029860273,"nu":0,"particle_id":42,"point":[-4.006449890432997,-0.1991719033668591,-0.2677197590261951],"type":1,"volume":0.026733958029860273},{"fixed":false,"mass":0.0611103943896377,"nu":0,"particle_id":43,"point":[-3.827309721067169,-0.4061733865595524,-0.4464451220022018],"type":1,"volume":0.0611103943896377},{"fixed":false,"mass":0.04955771362005426,"nu":0,"particle_id":44,"point":[-3.709832170994791,0.01375947885433382,-0.2486591502968405],"type":1,"volume":0.04955771362005426},{"fixed":false,"mass":0.0358926616277714,"nu":0,"particle_id":45,"point":[2.300184183244939,0.6443992069322578,0.2480498447961973],"type":1,"volume":0.0358926616277714},{"fixed":false,"mass":0.04048944903124158,"nu":0,"particle_id":46,"point":[2.291455805268016,0.2646108744755237,0.1827930918194401],"type":1,"volume":0.04048944903124158},{"fixed":false,"mass":0.04198381930621172,"nu":0,"particle_id":47,"point":[2.005228419850228,0.3110242200383387,0.03786000734078365],"type":1,"volume":0.04198381930621172},{"fixed":false,"mass":0.046019658028041824,"nu":0,"particle_id":48,"point":[2.262811974025447,0.4987179567116687,-0.07831154307128407],"type":1,"volume":0.046019658028041824},{"fixed":false,"mass":0.030272502736832227,"nu":0,"particle_id":49,"point":[-1.980513380690766,0.282215434506385,-0.20537402231552],"type":1,"volume":0.030272502736832227},{"fixed":false,"mass":0.029414348603175062,"nu":0,"particle_id":50,"point":[-2.02514794527919,0.2228317835278485,0.2286519065384029],"type":1,"volume":0.029414348603175062},{"fixed":false,"mass":0.03637849075256033,"nu":0,"particle_id":51,"point":[-1.751503241107395,0.3027956943796303,0.03590712555120758],"type":1,"volume":0.03637849075256033},{"fixed":false,"mass":0.052180746822492484,"nu":0,"particle_id":52,"point":[-2.131743152860462,0.4856842477720718,0.05101062130692252],"type":1,"volume":0.052180746822492484},{"fixed":false,"mass":0.062000633657663576,"nu":0,"particle_id":53,"point":[3.794757863241868,-0.004136862470872707,-0.511249042299535],"type":1,"volume":0.062000633657663576},{"fixed":false,"mass":0.06719113976633666,"nu":0,"particle_id":54,"point":[3.38744552538545,0.2444411091196344,-0.4819660547089512],"type":1,"volume":0.06719113976633666},{"fixed":false,"mass":0.03967670063058805,"nu":0,"particle_id":55,"point":[3.714728074421184,0.3975219399712127,-0.564785539589304],"type":1,"volume":0.03967670063058805},{"fixed":false,"mass":0.02938817294318692,"nu":0,"particle_id":56,"point":[3.586693017596381,0.06679671577746861,-0.9934210977234275],"type":1,"volume":0.02938817294318692},{"fixed":false,"mass":0.020962736219560234,"nu":0,"particle_id":57,"point":[-2.886888848162905,0.3392251215474296,-0.937062466973001],"type":1,"volume":0.020962736219560234},{"fixed":false,"mass":0.05603944588112993,"nu":0,"particle_id":58,"point":[-3.001088910261564,0.4178438313858495,-0.381191636526935],"type":1,"volume":0.05603944588112993},{"fixed":false,"mass":0.056497647817983665,"nu":0,"particle_id":59,"point":[-2.948224730042449,0.0005444167515062676,-0.5316653149372895],"type":1,"volume":0.056497647817983665},{"fixed":false,"mass":0.059080764597205994,"nu":0,"particle_id":60,"point":[-2.632537050480965,0.2637141143860336,-0.526336623665504],"type":1,"volume":0.059080764597205994},{"fixed":false,"mass":0.024735616692548017,"nu":0,"particle_id":61,"point":[-4.134808487816516,0.6860716192372633,-0.7243698924599702],"type":1,"volume":0.024735616692548017},{"fixed":false,"mass":0.021291662689371063,"nu":0,"particle_id":62,"point":[-3.772261540250631,0.5389652345127409,-0.840345168916909],"type":1,"volume":0.021291662689371063},{"fixed":false,"mass":0.04232616277561355,"nu":0,"particle_id":63,"point":[-4.165527657125383,0.2810700091373977,-0.5899010033265667],"type":1,"volume":0.04232616277561355},{"fixed":false,"mass":0.01778072113255871,"nu":0,"particle_id":64,"point":[-3.994203897035045,0.295950675022332,-0.9501896268113327],"type":1,"volume":0.01778072113255871},{"fixed":false,"mass":0.0152911903149972,"nu":0,"particle_id":65,"point":[-4.163450245999107,-0.002851585926546848,-0.9997191433003008],"type":1,"volume":0.0152911903149972},{"fixed":false,"mass":0.009773087941473281,"nu":0,"particle_id":66,"point":[3.875136169143151,-0.914943533056152,0.3994015114734688],"type":1,"volume":0.009773087941473281},{"fixed":false,"mass":0.007935437244414182,"nu":0,"particle_id":67,"point":[3.711213379384667,-0.8317362176760836,0.5550714494478339],"type":1,"volume":0.007935437244414182},{"fixed":false,"mass":0.06124018713388065,"nu":0,"particle_id":68,"point":[3.765406986819124,-0.5160342745431523,0.1366790220410407],"type":1,"volume":0.06124018713388065},{"fixed":false,"mass":0.0553195611313843,"nu":0,"particle_id":69,"point":[-2.452085663670125,0.1723458187824141,0.3359880020836931],"type":1,"volume":0.0553195611313843},{"fixed":false,"mass":0.06695790114868191,"nu":0,"particle_id":70,"point":[-2.657001546581177,-0.2401012859342282,0.4922530147492091],"type":1,"volume":0.06695790114868191},{"fixed":false,"mass":0.038979519934159525,"nu":0,"particle_id":71,"point":[-2.666235304960422,0.110374522219687,0.6483957395881291],"type":1,"volume":0.038979519934159525},{"fixed":false,"mass":0.03371657605498231,"nu":0,"particle_id":72,"point":[-2.877494598898519,-0.04924260156833288,0.3165377806484523],"type":1,"volume":0.03371657605498231},{"fixed":false,"mass":0.015189372697222382,"nu":0,"particle_id":73,"point":[3.942437038659111,0.9950058980689935,0.05070596783859541],"type":1,"volume":0.015189372697222382},{"fixed":false,"mass":0.04741909727899588,"nu":0,"particle_id":74,"point":[3.835234840371672,0.5880263815598717,0.3658945715316854],"type":1,"volume":0.04741909727899588},{"fixed":false,"mass":0.055426982920167046,"nu":0,"particle_id":75,"point":[3.608208811814772,0.5904886110966465,0.0734924615659597],"type":1,"volume":0.055426982920167046},{"fixed":false,"mass":0.07164473328071158,"nu":0,"particle_id":76,"point":[4.133811929341112,0.6281570694088763,0.02135220424911416],"type":1,"volume":0.07164473328071158},{"fixed":false,"mass":0.0266250694971627,"nu":0,"particle_id":77,"point":[-3.171978648913057,-0.1020033080336953,0.9899535510446882],"type":1,"volume":0.0266250694971627},{"fixed":false,"mass":0.04350291982245184,"nu":0,"particle_id":78,"point":[-3.221795091019529,0.125143559246671,0.6588714069930013],"type":1,"volume":0.04350291982245184},{"fixed":false,"mass":0.029893664048290625,"nu":0,"particle_id":79,"point":[-3.031138812059015,0.2688050125016094,0.9584241735113179],"type":1,"volume":0.029893664048290625},{"fixed":false,"mass":0.02923560789763644,"nu":0,"particle_id":80,"point":[-2.948015794283009,-0.06841706834718703,0.7039474490094711],"type":1,"volume":0.02923560789763644},{"fixed":false,"mass":0.020324919338227568,"nu":0,"particle_id":81,"point":[4.470227610638783,0.07446050698183375,0.9926662801726733],"type":1,"volume":0.020324919338227568},{"fixed":false,"mass":0.06552765076101777,"nu":0,"particle_id":82,"point":[4.641835345585677,-0.1910457981121732,0.5769069859138221],"type":1,"volume":0.06552765076101777},{"fixed":false,"mass":0.028944193284204184,"nu":0,"particle_id":83,"point":[4.766424746303289,0.1739255652142404,0.6764622457309343],"type":1,"volume":0.028944193284204184},{"fixed":false,"mass":0.008998692640504338,"nu":0,"particle_id":84,"point":[4.66912773738998,-0.01095229350137986,0.99892129324307],"type":1,"volume":0.008998692640504338},{"fixed":false,"mass":0.01887334696847653,"nu":0,"particle_id":85,"point":[-3.473494931985415,0.8551027956553141,0.5113556568148803],"type":1,"volume":0.01887334696847653},{"fixed":false,"mass":0.012066245768636217,"nu":0,"particle_id":86,"point":[-3.158471419156117,0.8424614256312881,0.5350059966745715],"type":1,"volume":0.012066245768636217},{"fixed":false,"mass":0.045777473332350764,"nu":0,"particle_id":87,"point":[-3.244036160779,0.4966376885717967,0.4005412544482952],"type":1,"volume":0.045777473332350764},{"fixed":false,"mass":0.022385839573594832,"nu":0,"particle_id":88,"point":[-3.358524527244523,0.9818977337158312,0.1837953939850322],"type":1,"volume":0.022385839573594832},{"fixed":false,"mass":0.02492138190271746,"nu":0,"particle_id":89,"point":[-2.429314665521927,-0.7847625600294974,-0.6124829408841327],"type":1,"volume":0.02492138190271746},{"fixed":false,"mass":0.015244736416341881,"nu":0,"particle_id":90,"point":[-2.299630135667146,-0.3964613725420245,-0.9165150700562513],"type":1,"volume":0.015244736416341881},{"fixed":false,"mass":0.01174199713923391,"nu":0,"particle_id":91,"point":[-2.183433358912889,-0.727429130642447,-0.6823439267263032],"type":1,"volume":0.01174199713923391},{"fixed":false,"mass":0.01797165228028419,"nu":0,"particle_id":92,"point":[-1.248285031511733,0.9931103936369955,0.06995134730713878],"type":1,"volume":0.01797165228028419},{"fixed":false,"mass":0.011207159460904087,"nu":0,"particle_id":93,"point":[-0.8828673024779388,0.9901786573787905,-0.0997177650682256],"type":1,"volume":0.011207159460904087},{"fixed":false,"mass":0.02452171711879411,"nu":0,"particle_id":94,"point":[-0.8636269119618498,0.9477091808074602,0.3041276096582257],"type":1,"volume":0.02452171711879411},{"fixed":false,"mass":0.012162340458130276,"nu":0,"particle_id":95,"point":[4.625131757323569,-0.7309668637931728,-0.678033186409555],"type":1,"volume":0.012162340458130276},{"fixed":false,"mass":0.010331519878261888,"nu":0,"particle_id":96,"point":[5,-0.8255475727255929,-0.5627862591227902],"type":2,"volume":0.010331519878261888},{"fixed":false,"mass":0.04922215799184319,"nu":0,"particle_id":97,"point":[4.731443049693974,-0.5082603891272319,-0.4240549369798206],"type":1,"volume":0.04922215799184319},{"fixed":false,"mass":0.012845635539748339,"nu":0,"particle_id":98,"point":[4.639413286153015,-0.8930004658127295,-0.4404541028369581],"type":1,"volume":0.012845635539748339},{"fixed":false,"mass":0.0415740283488638,"nu":0,"particle_id":99,"point":[2.726271162374811,0.4194926846088941,-0.2264019549683927],"type":1,"volume":0.0415740283488638},{"fixed":false,"mass":0.04434636188419469,"nu":0,"particle_id":100,"point":[2.482100586403666,0.2023428111795482,-0.2587750445329458],"type":1,"volume":0.04434636188419469},{"fixed":false,"mass":0.03350065504483024,"nu":0,"particle_id":101,"point":[2.630417818503024,0.3823542062172355,-0.5708564806077383],"type":1,"volume":0.03350065504483024},{"fixed":false,"mass":0.048198236203256764,"nu":0,"particle_id":102,"point":[2.613208399173119,0.04821555445505243,-0.5173806995248806],"type":1,"volume":0.048198236203256764},{"fixed":false,"mass":0.01563566998582991,"nu":0,"particle_id":103,"point":[2.359410257644354,-0.2218500007179617,-0.9726678206146318],"type":1,"volume":0.01563566998582991},{"fixed":false,"mass":0.04245496335124077,"nu":0,"particle_id":104,"point":[2.485021502642345,-0.2684493881879212,-0.6065524476145281],"type":1,"volume":0.04245496335124077},{"fixed":false,"mass":0.020608491795495964,"nu":0,"particle_id":105,"point":[2.07136768782369,-0.2542339570198517,-0.9628442548683678],"type":1,"volume":0.020608491795495964},{"fixed":false,"mass":0.042622257385584554,"nu":0,"particle_id":106,"point":[2.903495434461601,-0.611315087520766,-0.06045751580979139],"type":1,"volume":0.042622257385584554},{"fixed":false,"mass":0.026812109857870775,"nu":0,"particle_id":107,"point":[3.209619685308639,-0.7493044711448648,0.07383366403101324],"type":1,"volume":0.026812109857870775},{"fixed":false,"mass":0.018427730125859222,"nu":0,"particle_id":108,"point":[3.004478551053779,0.9967494973367,0.03300290738586065],"type":1,"volume":0.018427730125859222},{"fixed":false,"mass":0.054031996088323084,"nu":0,"particle_id":109,"point":[3.031195686285311,0.6226924837950327,-0.267716357753779],"type":1,"volume":0.054031996088323084},{"fixed":false,"mass":0.0273730865105633,"nu":0,"particle_id":110,"point":[2.865232750361471,0.9509856974164264,-0.2933263819342162],"type":1,"volume":0.0273730865105633},{"fixed":false,"mass":0.01738075977794174,"nu":0,"particle_id":111,"point":[3.303494366453592,0.9614278671480658,-0.2589031615862529],"type":1,"volume":0.01738075977794174},{"fixed":false,"mass":0.04175792878178565,"nu":0,"particle_id":112,"point":[-0.9179192611273244,-0.5285992971443779,0.4012563113680896],"type":1,"volume":0.04175792878178565},{"fixed":false,"mass":0.033492192110906226,"nu":0,"particle_id":113,"point":[-1.16698042413296,-0.2609363612989061,0.6697467614891082],"type":1,"volume":0.033492192110906226},{"fixed":false,"mass":0.0497308649233907,"nu":0,"particle_id":114,"point":[-1.26445286206162,-0.4463301434603677,0.3791146994252123],"type":1,"volume":0.0497308649233907},{"fixed":false,"mass":0.013800538609696733,"nu":0,"particle_id":115,"point":[-1.028532793874813,-0.7162333660987635,0.6959860052944342],"type":1,"volume":0.013800538609696733},{"fixed":false,"mass":0.05104898920452672,"nu":0,"particle_id":116,"point":[-0.8682995986733436,0.3724337213499915,-0.3439806528218857],"type":1,"volume":0.05104898920452672},{"fixed":false,"mass":0.015338087683882836,"nu":0,"particle_id":117,"point":[-1.01116452364028,0.7037806021603097,-0.70983650576788],"type":1,"volume":0.015338087683882836},{"fixed":false,"mass":0.03814371303425343,"nu":0,"particle_id":118,"point":[-1.142573192933489,0.5981281595684412,-0.3616162319985682],"type":1,"volume":0.03814371303425343},{"fixed":false,"mass":0.015473931704047993,"nu":0,"particle_id":119,"point":[-0.9068978359538125,0.8595001219446659,-0.503128837963801],"type":1,"volume":0.015473931704047993},{"fixed":false,"mass":0.05951023214044787,"nu":0,"particle_id":120,"point":[1.644430629452296,-0.2422453764238503,-0.3770072205984468],"type":1,"volume":0.05951023214044787},{"fixed":false,"mass":0.05186599901226912,"nu":0,"particle_id":121,"point":[1.553509101920363,-0.2717274887044852,-0.0271684343837898],"type":1,"volume":0.05186599901226912},{"fixed":false,"mass":0.048571334739899365,"nu":0,"particle_id":122,"point":[1.877994461028244,-0.3423147572615952,0.1186046244977769],"type":1,"volume":0.048571334739899365},{"fixed":false,"mass":0.019107503931947913,"nu":0,"particle_id":123,"point":[-4.23382319833847,-0.3678757040352918,0.9283714077918894],"type":1,"volume":0.019107503931947913},{"fixed":false,"mass":0.042791074496450025,"nu":0,"particle_id":124,"point":[-4.286868845923317,-0.006749008237184329,0.6873116441004872],"type":1,"volume":0.042791074496450025},{"fixed":false,"mass":0.017457686213554268,"nu":0,"particle_id":125,"point":[-4.469528185181522,-0.1206298150342931,0.9881190002305573],"type":1,"volume":0.017457686213554268},{"fixed":false,"mass":0.009187687956726073,"nu":0,"particle_id":126,"point":[-4.121842564707817,-0.1093257466001983,0.9892323537942768],"type":1,"volume":0.009187687956726073},{"fixed":false,"mass":0.01967202309705833,"nu":0,"particle_id":127,"point":[-1.497297833742455,0.7730425430140191,0.6267638229374444],"type":1,"volume":0.01967202309705833},{"fixed":false,"mass":0.033399541320003646,"nu":0,"particle_id":128,"point":[-0.9989351068213506,0.7197641802245641,0.6916836958339504],"type":1,"volume":0.033399541320003646},{"fixed":false,"mass":0.053998447117040674,"nu":0,"particle_id":129,"point":[-1.422027367440409,0.5498804681824593,0.3116864555503576],"type":1,"volume":0.053998447117040674},{"fixed":false,"mass":0.025076391600170982,"nu":0,"particle_id":130,"point":[-1.234654648671424,0.8838788673250885,0.4575194133125117],"type":1,"volume":0.025076391600170982},{"fixed":false,"mass":0.05325489740221358,"nu":0,"particle_id":131,"point":[-2.222809708544816,-0.4682152286517877,-0.3009835829689027],"type":1,"volume":0.05325489740221358},{"fixed":false,"mass":0.017176132138938188,"nu":0,"particle_id":132,"point":[-2.000976054972893,-0.842963877563046,-0.5340659752270032],"type":1,"volume":0.017176132138938188},{"fixed":false,"mass":0.03276955556881834,"nu":0,"particle_id":133,"point":[-2.127882474572919,-0.7152992946383896,-0.0705832773266464],"type":1,"volume":0.03276955556881834},{"fixed":false,"mass":0.017000344905002927,"nu":0,"particle_id":134,"point":[-4.581174487303853,0.1658744873198582,0.9836627889627169],"type":1,"volume":0.017000344905002927},{"fixed":false,"mass":0.016815502398507085,"nu":0,"particle_id":135,"point":[-4.08394799071251,0.1763527752889206,0.9826307676758634],"type":1,"volume":0.016815502398507085},{"fixed":false,"mass":0.07122160409049327,"nu":0,"particle_id":136,"point":[2.584406117911328,0.4282841933368184,0.2885918838631453],"type":1,"volume":0.07122160409049327},{"fixed":false,"mass":0.04352441592228286,"nu":0,"particle_id":137,"point":[2.669674616520518,-0.06333015432216049,0.2387578156964944],"type":1,"volume":0.04352441592228286},{"fixed":false,"mass":0.03508065828659006,"nu":0,"particle_id":138,"point":[2.439190042674461,0.003483285209622544,-0.001025303900104912],"type":1,"volume":0.03508065828659006},{"fixed":false,"mass":0.04507748622520616,"nu":0,"particle_id":139,"point":[2.836972291389031,0.09057463102152422,-0.01305148508178539],"type":1,"volume":0.04507748622520616},{"fixed":false,"mass":0.020478523228076417,"nu":0,"particle_id":140,"point":[3.768427928956693,-0.70598721601205,-0.7080255845802081],"type":1,"volume":0.020478523228076417},{"fixed":false,"mass":0.049035754952812406,"nu":0,"particle_id":141,"point":[3.901214334166843,-0.3774401560656327,-0.5416524397414633],"type":1,"volume":0.049035754952812406},{"fixed":false,"mass":0.011367353919784459,"nu":0,"particle_id":142,"point":[4.037616390941182,-0.6989597369872793,-0.7137928875688306],"type":1,"volume":0.011367353919784459},{"fixed":false,"mass":0.014174200421622775,"nu":0,"particle_id":143,"point":[3.712953920413026,-0.5003755566962815,-0.8609717814425597],"type":1,"volume":0.014174200421622775},{"fixed":false,"mass":0.02454320507947816,"nu":0,"particle_id":144,"point":[3.755971535920696,0.7566817200312581,-0.6466995434234597],"type":1,"volume":0.02454320507947816},{"fixed":false,"mass":0.043541275909343195,"nu":0,"particle_id":145,"point":[3.8569831839802,0.4423401131255426,-0.2254310200778576],"type":1,"volume":0.043541275909343195},{"fixed":false,"mass":0.06077121442951237,"nu":0,"particle_id":146,"point":[4.166917116178171,0.4526310252409118,-0.4630479163559781],"type":1,"volume":0.06077121442951237},{"fixed":false,"mass":0.03376643982001596,"nu":0,"particle_id":147,"point":[-2.291229868911083,0.5166338518804474,0.400559509822827],"type":1,"volume":0.03376643982001596},{"fixed":false,"mass":0.05813814043635522,"nu":0,"particle_id":148,"point":[-2.089019738922628,0.1602425315893123,0.5511629326689705],"type":1,"volume":0.05813814043635522},{"fixed":false,"mass":0.031490956750285404,"nu":0,"particle_id":149,"point":[-1.982771627538392,0.5950715980010555,0.4643996093569837],"type":1,"volume":0.031490956750285404},{"fixed":false,"mass":0.040863336256105526,"nu":0,"particle_id":150,"point":[0.2804890241801438,-0.1807348725153986,-0.2469684450307683],"type":1,"volume":0.040863336256105526},{"fixed":false,"mass":0.029248526059206695,"nu":0,"particle_id":151,"point":[0.1464929224144694,0.001887809785750094,0.002374694646108066],"type":1,"volume":0.029248526059206695},{"fixed":false,"mass":0.031870734686458735,"nu":0,"particle_id":152,"point":[-0.02719704938420842,-0.2708609224709452,-0.1219719952587592],"type":1,"volume":0.031870734686458735},{"fixed":false,"mass":0.035366386188934264,"nu":0,"particle_id":153,"point":[0.3580969970421717,-0.2519687569508218,0.09900697936266609],"type":1,"volume":0.035366386188934264},{"fixed":false,"mass":0.03164152165882779,"nu":0,"particle_id":154,"point":[-0.09706948033881332,-0.1114279694290356,0.2495328926244624],"type":1,"volume":0.03164152165882779},{"fixed":false,"mass":0.06220567887781521,"nu":0,"particle_id":155,"point":[-0.06142881306223297,-0.433705501208198,0.2244594002694189],"type":1,"volume":0.06220567887781521},{"fixed":false,"mass":0.05581128152118555,"nu":0,"particle_id":156,"point":[-0.6113005999645312,-0.1565625978970077,0.1059926925979835],"type":1,"volume":0.05581128152118555},{"fixed":false,"mass":0.0347185406990124,"nu":0,"particle_id":157,"point":[-0.263994416510661,-0.03939980615759548,-0.02011456991178084],"type":1,"volume":0.0347185406990124},{"fixed":false,"mass":0.06096333072034879,"nu":0,"particle_id":158,"point":[4.316342829477622,0.4668793652655274,0.4988115372624441],"type":1,"volume":0.06096333072034879},{"fixed":false,"mass":0.018411999350241032,"nu":0,"particle_id":159,"point":[4.358631440599966,0.3224217010924196,0.9421597288412875],"type":1,"volume":0.018411999350241032},{"fixed":false,"mass":0.012778122939765511,"nu":0,"particle_id":160,"point":[4.577394873011919,0.6205798941161924,0.7781175622416145],"type":1,"volume":0.012778122939765511},{"fixed":false,"mass":0.019258254157291224,"nu":0,"particle_id":161,"point":[4.125111369461218,0.6568414038131144,0.7483585103099228],"type":1,"volume":0.019258254157291224},{"fixed":false,"mass":0.017317057508588984,"nu":0,"particle_id":162,"point":[2.637986448701776,0.2932124143793697,-0.9510202690962278],"type":1,"volume":0.017317057508588984},{"fixed":false,"mass":0.05072312281229734,"nu":0,"particle_id":163,"point":[2.954745868257494,0.2865624473144734,-0.549887051757129],"type":1,"volume":0.05072312281229734},{"fixed":false,"mass":0.011259576563896001,"nu":0,"particle_id":164,"point":[2.788659094336903,0.5216073083549893,-0.8496231737452388],"type":1,"volume":0.011259576563896001},{"fixed":false,"mass":0.020084509525193705,"nu":0,"particle_id":165,"point":[1.622883894408121,-0.9623097974996764,-0.2559958268459387],"type":1,"volume":0.020084509525193705},{"fixed":false,"mass":0.00860322199108107,"nu":0,"particle_id":166,"point":[1.695184023569132,-0.9981469377263299,-0.01881445700342388],"type":1,"volume":0.00860322199108107},{"fixed":false,"mass":0.0441936931984438,"nu":0,"particle_id":167,"point":[1.669020333349457,-0.6364484718535957,0.04507227898337507],"type":1,"volume":0.0441936931984438},{"fixed":false,"mass":0.018308272626710035,"nu":0,"particle_id":168,"point":[1.445973895768965,-0.9993236560842135,0.006867035017603131],"type":1,"volume":0.018308272626710035},{"fixed":false,"mass":0.011126473967407744,"nu":0,"particle_id":169,"point":[5,-0.07432012267281404,0.992680106820278],"type":2,"volume":0.011126473967407744},{"fixed":false,"mass":0.06548699959659099,"nu":0,"particle_id":170,"point":[1.430549334342659,0.4200101697179852,-0.3345195065694664],"type":1,"volume":0.06548699959659099},{"fixed":false,"mass":0.03243712803820598,"nu":0,"particle_id":171,"point":[1.251420724789132,0.3438361015556008,-0.6014364019936695],"type":1,"volume":0.03243712803820598},{"fixed":false,"mass":0.045990435353122104,"nu":0,"particle_id":172,"point":[1.230926238145538,-0.08206898078811309,-0.3249167633466765],"type":1,"volume":0.045990435353122104},{"fixed":false,"mass":0.04500040396672952,"nu":0,"particle_id":173,"point":[1.025235287984389,0.1749554597692072,-0.4298157345577643],"type":1,"volume":0.04500040396672952},{"fixed":false,"mass":0.030215402254849286,"nu":0,"particle_id":174,"point":[1.043043084670435,-0.6187282275555388,-0.7796371857156297],"type":1,"volume":0.030215402254849286},{"fixed":false,"mass":0.041252884712704954,"nu":0,"particle_id":175,"point":[1.041722161137601,-0.1750643779343342,-0.6329610106790413],"type":1,"volume":0.041252884712704954},{"fixed":false,"mass":0.023478397021505684,"nu":0,"particle_id":176,"point":[1.277311137273452,-0.16744637283478,-0.9835079717524355],"type":1,"volume":0.023478397021505684},{"fixed":false,"mass":0.019047552409874487,"nu":0,"particle_id":177,"point":[0.8228275448557336,-0.3097870455998258,-0.9459924096834877],"type":1,"volume":0.019047552409874487},{"fixed":false,"mass":0.05353149841073262,"nu":0,"particle_id":178,"point":[-2.611153228887777,-0.4293544633449046,-0.5039926659942123],"type":1,"volume":0.05353149841073262},{"fixed":false,"mass":0.05160049967370638,"nu":0,"particle_id":179,"point":[-0.887673808786921,-0.3444202559562685,-0.4338308153953075],"type":1,"volume":0.05160049967370638},{"fixed":false,"mass":0.054387177448447364,"nu":0,"particle_id":180,"point":[-0.6530675834219872,-0.08278083959971977,-0.2586588510580682],"type":1,"volume":0.054387177448447364},{"fixed":false,"mass":0.05711715299782085,"nu":0,"particle_id":181,"point":[-0.8721552983896601,0.04090107388217843,-0.6047349965454134],"type":1,"volume":0.05711715299782085},{"fixed":false,"mass":0.043907051297024456,"nu":0,"particle_id":182,"point":[-1.140498698538972,-0.2094897876607019,-0.209791237887078],"type":1,"volume":0.043907051297024456},{"fixed":false,"mass":0.012388147453784384,"nu":0,"particle_id":183,"point":[-3.779967116720712,-0.8171733690047049,0.5729902558806841],"type":1,"volume":0.012388147453784384},{"fixed":false,"mass":0.01933593070719012,"nu":0,"particle_id":184,"point":[-3.741976998362208,-0.6349214103091385,0.7663477840737378],"type":1,"volume":0.01933593070719012},{"fixed":false,"mass":0.0383827906843849,"nu":0,"particle_id":185,"point":[-3.774762518072331,-0.6368660553408199,0.294612446407196],"type":1,"volume":0.0383827906843849},{"fixed":false,"mass":0.0529803305091851,"nu":0,"particle_id":186,"point":[-3.765298815547263,-0.3454276660684436,0.5809187025032959],"type":1,"volume":0.0529803305091851},{"fixed":false,"mass":0.010761422143047223,"nu":0,"particle_id":187,"point":[-1.355220484814595,0.9818851458304712,-0.1839232009299126],"type":1,"volume":0.010761422143047223},{"fixed":false,"mass":0.038432233012205747,"nu":0,"particle_id":188,"point":[-1.448533113431858,0.7231388867266131,0.02066803818219076],"type":1,"volume":0.038432233012205747},{"fixed":false,"mass":0.060107954321520884,"nu":0,"particle_id":189,"point":[1.976080069676443,-0.4980590251520869,-0.272009537878146],"type":1,"volume":0.060107954321520884},{"fixed":false,"mass":0.052083910525175185,"nu":0,"particle_id":190,"point":[2.314304501904654,-0.5276462815449436,0.03924412561754409],"type":1,"volume":0.052083910525175185},{"fixed":false,"mass":0.0366237249091505,"nu":0,"particle_id":191,"point":[2.006865962016344,-0.6645890904191989,0.01950606374945546],"type":1,"volume":0.0366237249091505},{"fixed":false,"mass":0.037950981790897474,"nu":0,"particle_id":192,"point":[4.718459257846357,0.6138550570378866,0.3324436665725002],"type":1,"volume":0.037950981790897474},{"fixed":false,"mass":0.012568012567323122,"nu":0,"particle_id":193,"point":[5,0.7307949394943561,0.6782426767737967],"type":2,"volume":0.012568012567323122},{"fixed":false,"mass":0.015584940717585496,"nu":0,"particle_id":194,"point":[5,0.5655812075058759,0.1738274711702137],"type":2,"volume":0.015584940717585496},{"fixed":false,"mass":0.007139636409697404,"nu":0,"particle_id":195,"point":[5,0.8974766981659316,0.4320796611235228],"type":2,"volume":0.007139636409697404},{"fixed":false,"mass":0.05130388272332369,"nu":0,"particle_id":196,"point":[-0.2134640623790376,0.2210589010719869,0.2014659959138561],"type":1,"volume":0.05130388272332369},{"fixed":false,"mass":0.04118520515664656,"nu":0,"particle_id":197,"point":[-0.3900603800425489,-0.04366305435182782,0.3733310898966431],"type":1,"volume":0.04118520515664656},{"fixed":false,"mass":0.060971969387388386,"nu":0,"particle_id":198,"point":[-0.7078602687043036,0.2200208281606869,0.5286331338903687],"type":1,"volume":0.060971969387388386},{"fixed":false,"mass":0.026784986748697427,"nu":0,"particle_id":199,"point":[2.546725285247547,0.9976720016701037,-0.02363656370550522],"type":1,"volume":0.026784986748697427},{"fixed":false,"mass":0.01841967890201672,"nu":0,"particle_id":200,"point":[2.241944656227243,0.9910743258764679,-0.09062389020049263],"type":1,"volume":0.01841967890201672},{"fixed":false,"mass":0.05378750652672684,"nu":0,"particle_id":201,"point":[2.622861250459029,0.04993176822089493,0.555085754055386],"type":1,"volume":0.05378750652672684},{"fixed":false,"mass":0.052632587234752615,"nu":0,"particle_id":202,"point":[2.31475823389354,0.2965986146807879,0.5451454618673544],"type":1,"volume":0.052632587234752615},{"fixed":false,"mass":0.04503448182416673,"nu":0,"particle_id":203,"point":[2.815098962522789,0.3659362227269857,0.5945549112474449],"type":1,"volume":0.04503448182416673},{"fixed":false,"mass":0.014791410382874026,"nu":0,"particle_id":204,"point":[0.1703611195455475,-0.6525684058432695,-0.7518652691170287],"type":1,"volume":0.014791410382874026},{"fixed":false,"mass":0.04980822863146771,"nu":0,"particle_id":205,"point":[0.3539926782200524,-0.411265318133516,-0.5248426881142152],"type":1,"volume":0.04980822863146771},{"fixed":false,"mass":0.02142049848705028,"nu":0,"particle_id":206,"point":[0.220684816381087,-0.9211462254393796,-0.3877970902256412],"type":1,"volume":0.02142049848705028},{"fixed":false,"mass":0.01670417280933862,"nu":0,"particle_id":207,"point":[0.5616357209188636,-0.842483800929847,-0.5349641354352934],"type":1,"volume":0.01670417280933862},{"fixed":false,"mass":0.0215612287944107,"nu":0,"particle_id":208,"point":[2.16817532706386,-0.9637735709995014,-0.251170412299064],"type":1,"volume":0.0215612287944107},{"fixed":false,"mass":0.025125617150472873,"nu":0,"particle_id":209,"point":[2.396758771419484,-0.9835269635599491,0.1672535457771258],"type":1,"volume":0.025125617150472873},{"fixed":false,"mass":0.006067522069155262,"nu":0,"particle_id":210,"point":[2.032904639564197,-0.9970294301939139,-0.03016070138947838],"type":1,"volume":0.006067522069155262},{"fixed":false,"mass":0.012640512265626618,"nu":0,"particle_id":211,"point":[1.945895670362404,-0.971022653565871,0.2272733896576272],"type":1,"volume":0.012640512265626618},{"fixed":false,"mass":0.007420863877725041,"nu":0,"particle_id":212,"point":[1.672920879932996,-0.9704429429707955,0.2291844393786319],"type":1,"volume":0.007420863877725041},{"fixed":false,"mass":0.040795126287506506,"nu":0,"particle_id":213,"point":[-1.923737019039039,-0.000344896793819327,0.000795864579972605],"type":1,"volume":0.040795126287506506},{"fixed":false,"mass":0.06602767342440348,"nu":0,"particle_id":214,"point":[-1.791359981000157,0.2192192983831051,-0.472466256690376],"type":1,"volume":0.06602767342440348},{"fixed":false,"mass":0.050987091718431736,"nu":0,"particle_id":215,"point":[-2.118928599763412,-0.1321005404325298,-0.2632643652326372],"type":1,"volume":0.050987091718431736},{"fixed":false,"mass":0.049994943224380174,"nu":0,"particle_id":216,"point":[-4.244471378180799,0.1057116680236929,-0.2667330604326831],"type":1,"volume":0.049994943224380174},{"fixed":false,"mass":0.04297700513456141,"nu":0,"particle_id":217,"point":[-4.725438317961745,-0.5773980462217783,0.2950708099068466],"type":1,"volume":0.04297700513456141},{"fixed":false,"mass":0.014492263353722452,"nu":0,"particle_id":218,"point":[-4.628484382721567,-0.8491992531451185,0.522400408014861],"type":1,"volume":0.014492263353722452},{"fixed":false,"mass":0.012382845811234377,"nu":0,"particle_id":219,"point":[-4.66358723657406,-0.9644527878247422,0.248931334498168],"type":1,"volume":0.012382845811234377},{"fixed":false,"mass":0.016341496255111186,"nu":0,"particle_id":220,"point":[-4.401440881428885,-0.9644527878247422,0.2489313344981679],"type":1,"volume":0.016341496255111186},{"fixed":false,"mass":0.03955041570191596,"nu":0,"particle_id":221,"point":[-0.3901535293248091,0.1842105521367453,-0.3438313837875795],"type":1,"volume":0.03955041570191596},{"fixed":false,"mass":0.03466301497481085,"nu":0,"particle_id":222,"point":[-3.623269714118908,-0.3430659956403732,0.2669813898696893],"type":1,"volume":0.03466301497481085},{"fixed":false,"mass":0.05247254154781742,"nu":0,"particle_id":223,"point":[-3.656227582318592,-0.6099089907546833,-0.05906573067550146],"type":1,"volume":0.05247254154781742},{"fixed":false,"mass":0.060702493319177195,"nu":0,"particle_id":224,"point":[-3.321290032452492,-0.5229086454167138,0.387571731807778],"type":1,"volume":0.060702493319177195},{"fixed":false,"mass":0.03595135821568968,"nu":0,"particle_id":225,"point":[-2.650617719427015,0.5520397342339017,0.2657814980772468],"type":1,"volume":0.03595135821568968},{"fixed":false,"mass":0.02900406132160918,"nu":0,"particle_id":226,"point":[-2.933667413964816,0.6777611645461779,0.7311901063670876],"type":1,"volume":0.02900406132160918},{"fixed":false,"mass":0.01936680536307532,"nu":0,"particle_id":227,"point":[-2.523828202905612,0.7900189660264879,0.6060779916448782],"type":1,"volume":0.01936680536307532},{"fixed":false,"mass":0.020907363007720173,"nu":0,"particle_id":228,"point":[-2.85462350112455,0.8836524359803348,0.4579430365628506],"type":1,"volume":0.020907363007720173},{"fixed":false,"mass":0.015089619995901228,"nu":0,"particle_id":229,"point":[3.359579492739011,0.9989881649458106,-0.01027333370933159],"type":1,"volume":0.015089619995901228},{"fixed":false,"mass":0.04446024279119151,"nu":0,"particle_id":230,"point":[3.281346229988637,0.697286415061715,0.1575591175424584],"type":1,"volume":0.04446024279119151},{"fixed":false,"mass":0.014662313925626521,"nu":0,"particle_id":231,"point":[3.462530543582908,0.932582972035623,0.3539920373551405],"type":1,"volume":0.014662313925626521},{"fixed":false,"mass":0.014161336678009558,"nu":0,"particle_id":232,"point":[-1.623360153764553,-0.7420949084017059,-0.6644736248211564],"type":1,"volume":0.014161336678009558},{"fixed":false,"mass":0.017913092307185675,"nu":0,"particle_id":233,"point":[-1.479097255507918,-0.8717162118910101,-0.4802741411676075],"type":1,"volume":0.017913092307185675},{"fixed":false,"mass":0.012256178460108182,"nu":0,"particle_id":234,"point":[3.500380593621476,0.3239639023891315,-0.9416919071924755],"type":1,"volume":0.012256178460108182},{"fixed":false,"mass":0.013832789815259152,"nu":0,"particle_id":235,"point":[4.631652644816967,0.3646659590504711,0.9293450732882601],"type":1,"volume":0.013832789815259152},{"fixed":false,"mass":0.03861926476871549,"nu":0,"particle_id":236,"point":[4.554935918488046,0.1876211452607776,0.4946977090498405],"type":1,"volume":0.03861926476871549},{"fixed":false,"mass":0.02653039448595846,"nu":0,"particle_id":237,"point":[4.720631935337295,0.4323038046161671,0.5810832969751274],"type":1,"volume":0.02653039448595846},{"fixed":false,"mass":0.01821567544095969,"nu":0,"particle_id":238,"point":[-0.6211792601103627,0.4904260980424199,0.8662898778897307],"type":1,"volume":0.01821567544095969},{"fixed":false,"mass":0.024664833805207873,"nu":0,"particle_id":239,"point":[-0.9868704177975718,0.4172574606372655,0.9053993293851313],"type":1,"volume":0.024664833805207873},{"fixed":false,"mass":0.04518350807306459,"nu":0,"particle_id":240,"point":[-0.27449427764248,-0.4056946332562018,0.5155514033898181],"type":1,"volume":0.04518350807306459},{"fixed":false,"mass":0.013050651800567963,"nu":0,"particle_id":241,"point":[-0.2326689704870231,-0.7565715681208417,0.6468337639146514],"type":1,"volume":0.013050651800567963},{"fixed":false,"mass":0.02039743266602668,"nu":0,"particle_id":242,"point":[-0.4965898320700237,-0.8770694845646898,0.4702588724227248],"type":1,"volume":0.02039743266602668},{"fixed":false,"mass":0.046242392183584606,"nu":0,"particle_id":243,"point":[-0.3264956225904182,-0.6713137375296876,0.1127773888973282],"type":1,"volume":0.046242392183584606},{"fixed":false,"mass":0.03983341045496021,"nu":0,"particle_id":244,"point":[-1.423138983049572,0.3914759023133282,-0.04837945508626592],"type":1,"volume":0.03983341045496021},{"fixed":false,"mass":0.059241148077821854,"nu":0,"particle_id":245,"point":[-1.790502241547888,0.5560338705301527,-0.2031347055771224],"type":1,"volume":0.059241148077821854},{"fixed":false,"mass":0.06513612222917221,"nu":0,"particle_id":246,"point":[-1.421840575445583,0.4013357593315888,-0.4603961787381728],"type":1,"volume":0.06513612222917221},{"fixed":false,"mass":0.042399009052577555,"nu":0,"particle_id":247,"point":[-3.732257578167739,0.6967826845252046,-0.1806601967960424],"type":1,"volume":0.042399009052577555},{"fixed":false,"mass":0.05784585926394923,"nu":0,"particle_id":248,"point":[-3.5719548126761,0.573571802567078,0.1064926930596967],"type":1,"volume":0.05784585926394923},{"fixed":false,"mass":0.019208681182372338,"nu":0,"particle_id":249,"point":[-3.941251784932897,0.9659417848489575,0.244022769134906],"type":1,"volume":0.019208681182372338},{"fixed":false,"mass":0.05779099202540287,"nu":0,"particle_id":250,"point":[-3.991167229799399,0.4600377614269088,0.2208718282152309],"type":1,"volume":0.05779099202540287},{"fixed":false,"mass":0.027246604549729436,"nu":0,"particle_id":251,"point":[2.762286578011245,-0.7376769551758845,0.6698569164027024],"type":1,"volume":0.027246604549729436},{"fixed":false,"mass":0.010735431574733183,"nu":0,"particle_id":252,"point":[3.034092735540215,-0.7612969354802954,0.6410758871274593],"type":1,"volume":0.010735431574733183},{"fixed":false,"mass":0.016561369888202105,"nu":0,"particle_id":253,"point":[2.595660188112221,-0.8649499186531455,0.4929329854512324],"type":1,"volume":0.016561369888202105},{"fixed":false,"mass":0.01662252418821754,"nu":0,"particle_id":254,"point":[3.000738307978109,-0.9680713228748346,0.237002623074472],"type":1,"volume":0.01662252418821754},{"fixed":false,"mass":0.0385992546550043,"nu":0,"particle_id":255,"point":[-2.449315744489684,-0.0713669524833767,-0.3743628516285494],"type":1,"volume":0.0385992546550043},{"fixed":false,"mass":0.03795060692374416,"nu":0,"particle_id":256,"point":[1.551106646202626,0.08702337725439227,-0.2582411552341164],"type":1,"volume":0.03795060692374416},{"fixed":false,"mass":0.03172220774774193,"nu":0,"particle_id":257,"point":[1.313583252689975,-0.001201945660691317,0.0006634337775427435],"type":1,"volume":0.03172220774774193},{"fixed":false,"mass":0.017816547930799505,"nu":0,"particle_id":258,"point":[0.09208802368683108,-0.4091217359178557,-0.909747964846686],"type":1,"volume":0.017816547930799505},{"fixed":false,"mass":0.06008165912143045,"nu":0,"particle_id":259,"point":[0.2716134711824784,-0.006982382941184362,-0.6664299211162991],"type":1,"volume":0.06008165912143045},{"fixed":false,"mass":0.015536101042812698,"nu":0,"particle_id":260,"point":[0.3389758279346176,-0.246927908787645,-0.965060520369883],"type":1,"volume":0.015536101042812698},{"fixed":false,"mass":0.04784749485135373,"nu":0,"particle_id":261,"point":[-2.944818702593216,0.2634161078302794,0.4332942087887567],"type":1,"volume":0.04784749485135373},{"fixed":false,"mass":0.0437238782557406,"nu":0,"particle_id":262,"point":[-3.176326688331394,0.1982386649789024,0.1921049533601179],"type":1,"volume":0.0437238782557406},{"fixed":false,"mass":0.034009036436068896,"nu":0,"particle_id":263,"point":[-2.965965691998243,0.6264614454899238,0.2930695056117866],"type":1,"volume":0.034009036436068896},{"fixed":false,"mass":0.04346040122391015,"nu":0,"particle_id":264,"point":[2.055417967810698,-0.08953325585187866,0.2353308933121659],"type":1,"volume":0.04346040122391015},{"fixed":false,"mass":0.05057708996023517,"nu":0,"particle_id":265,"point":[1.764676645304604,0.154879474044467,0.6286521066553233],"type":1,"volume":0.05057708996023517},{"fixed":false,"mass":0.05246062891460717,"nu":0,"particle_id":266,"point":[2.091516092352272,0.01074983478114028,0.6442918335233909],"type":1,"volume":0.05246062891460717},{"fixed":false,"mass":0.031117675621858926,"nu":0,"particle_id":267,"point":[1.984114038263493,0.2131705042721856,0.3461857230812977],"type":1,"volume":0.031117675621858926},{"fixed":false,"mass":0.05547304614986795,"nu":0,"particle_id":268,"point":[0.7309734088374022,0.3579390469967677,-0.006241363408466163],"type":1,"volume":0.05547304614986795},{"fixed":false,"mass":0.0401365015605301,"nu":0,"particle_id":269,"point":[0.853561061423662,0.6785242834383576,0.183310649289318],"type":1,"volume":0.0401365015605301},{"fixed":false,"mass":0.04575876605048528,"nu":0,"particle_id":270,"point":[1.101590183673197,0.4390743630531485,0.2916818559268473],"type":1,"volume":0.04575876605048528},{"fixed":false,"mass":0.04271755112343119,"nu":0,"particle_id":271,"point":[1.104343149644603,0.2672802091653482,-0.002174111708990928],"type":1,"volume":0.04271755112343119},{"fixed":false,"mass":0.00919851023272194,"nu":0,"particle_id":272,"point":[-3.231236722780848,-0.8758218901060292,0.4725929574861566],"type":1,"volume":0.00919851023272194},{"fixed":false,"mass":0.0168190582496125,"nu":0,"particle_id":273,"point":[-3.466428530448789,-0.9634428730035238,0.2522605774923838],"type":1,"volume":0.0168190582496125},{"fixed":false,"mass":0.02401013675887693,"nu":0,"particle_id":274,"point":[-3.216398791279985,-0.9812936929618865,0.1899283226808908],"type":1,"volume":0.02401013675887693},{"fixed":false,"mass":0.07076483878508204,"nu":0,"particle_id":275,"point":[1.554823780941022,0.4707388199591795,0.1295872958796775],"type":1,"volume":0.07076483878508204},{"fixed":false,"mass":0.053422047586845996,"nu":0,"particle_id":276,"point":[-2.62022273422353,0.4233376160432277,-0.1477681476080798],"type":1,"volume":0.053422047586845996},{"fixed":false,"mass":0.05910514806405214,"nu":0,"particle_id":277,"point":[-2.845451448736572,0.6527111659690945,-0.007787336776908696],"type":1,"volume":0.05910514806405214},{"fixed":false,"mass":0.04000180720949578,"nu":0,"particle_id":278,"point":[-2.381518577149798,0.6982704059567557,0.1263086563368094],"type":1,"volume":0.04000180720949578},{"fixed":false,"mass":0.03910817554952516,"nu":0,"particle_id":279,"point":[-1.773091574405002,0.6721965948523088,0.1549563614052068],"type":1,"volume":0.03910817554952516},{"fixed":false,"mass":0.015325411380426474,"nu":0,"particle_id":280,"point":[-2.034778186200481,0.9104544300482976,0.4078000324881322],"type":1,"volume":0.015325411380426474},{"fixed":false,"mass":0.01637535209867751,"nu":0,"particle_id":281,"point":[-1.792545222838324,0.8594659063449056,0.5031928508485828],"type":1,"volume":0.01637535209867751},{"fixed":false,"mass":0.017656346798931827,"nu":0,"particle_id":282,"point":[0.2350680877926,0.9712696414793123,0.226459179624063],"type":1,"volume":0.017656346798931827},{"fixed":false,"mass":0.030415187250234937,"nu":0,"particle_id":283,"point":[0.1529835688709975,0.7178391426300462,0.04210563548242269],"type":1,"volume":0.030415187250234937},{"fixed":false,"mass":0.013447980754263811,"nu":0,"particle_id":284,"point":[-0.1208678341594148,0.9804772633125474,0.1961057182849126],"type":1,"volume":0.013447980754263811},{"fixed":false,"mass":0.02343919615845805,"nu":0,"particle_id":285,"point":[-0.000996725570332032,0.9899379122074039,-0.1021620918133083],"type":1,"volume":0.02343919615845805},{"fixed":false,"mass":0.031735324375432764,"nu":0,"particle_id":286,"point":[3.046994056986258,-0.27284413587787,0.2805486740089123],"type":1,"volume":0.031735324375432764},{"fixed":false,"mass":0.039072354941713475,"nu":0,"particle_id":287,"point":[3.380334696081101,-0.2337664317222884,0.492141658370375],"type":1,"volume":0.039072354941713475},{"fixed":false,"mass":0.04169501640729936,"nu":0,"particle_id":288,"point":[3.539639079218827,-0.2621639002949371,0.1888879882133574],"type":1,"volume":0.04169501640729936},{"fixed":false,"mass":0.05323534978424636,"nu":0,"particle_id":289,"point":[3.427630485844607,0.03704443987088646,0.2968284008021886],"type":1,"volume":0.05323534978424636},{"fixed":false,"mass":0.028991002883315596,"nu":0,"particle_id":290,"point":[-3.41416270451684,-0.4075758565052182,0.9105742546075777],"type":1,"volume":0.028991002883315596},{"fixed":false,"mass":0.01842891734161891,"nu":0,"particle_id":291,"point":[-3.289065043702408,-0.7010478329735143,0.7120792314797131],"type":1,"volume":0.01842891734161891},{"fixed":false,"mass":0.06967913169906889,"nu":0,"particle_id":292,"point":[-3.141320592060944,-0.2067330264623866,0.4632097902880986],"type":1,"volume":0.06967913169906889},{"fixed":false,"mass":0.03851907858295996,"nu":0,"particle_id":293,"point":[-2.962680613100149,-0.5571584134869701,0.830166226276968],"type":1,"volume":0.03851907858295996},{"fixed":false,"mass":0.011301215276519715,"nu":0,"particle_id":294,"point":[-3.533105913957828,-0.8706849070978435,0.4822035767280699],"type":1,"volume":0.011301215276519715},{"fixed":false,"mass":0.023715312126495674,"nu":0,"particle_id":295,"point":[-2.7990610233493,-0.4872616384065535,-0.8679813168043682],"type":1,"volume":0.023715312126495674},{"fixed":false,"mass":0.01617401185644291,"nu":0,"particle_id":296,"point":[-2.582530223245836,-0.2910931602588515,-0.951663137805408],"type":1,"volume":0.01617401185644291},{"fixed":false,"mass":0.04257179210822027,"nu":0,"particle_id":297,"point":[1.037985217786788,-0.002765015927167158,0.4745215382095789],"type":1,"volume":0.04257179210822027},{"fixed":false,"mass":0.03715949497904096,"nu":0,"particle_id":298,"point":[1.370506280614356,0.059701080397356,0.7259277672007878],"type":1,"volume":0.03715949497904096},{"fixed":false,"mass":0.037060557850992853,"nu":0,"particle_id":299,"point":[1.090142894490899,0.3084672600958548,0.6084266814381483],"type":1,"volume":0.037060557850992853},{"fixed":false,"mass":0.01917182863948494,"nu":0,"particle_id":300,"point":[1.163038135298975,0.1533766912592376,0.9848937144355991],"type":1,"volume":0.01917182863948494},{"fixed":false,"mass":0.045574511489821334,"nu":0,"particle_id":301,"point":[-0.7285076075350403,-0.6174674067085624,-0.2383004976020995],"type":1,"volume":0.045574511489821334},{"fixed":false,"mass":0.02467712863116148,"nu":0,"particle_id":302,"point":[-0.5913762356818428,-0.6328143140029423,-0.7680770333224666],"type":1,"volume":0.02467712863116148},{"fixed":false,"mass":0.04868572853119623,"nu":0,"particle_id":303,"point":[-0.413921160710782,-0.5624826759007344,-0.4484830759148495],"type":1,"volume":0.04868572853119623},{"fixed":false,"mass":0.034838045457373304,"nu":0,"particle_id":304,"point":[0.3785156675896414,0.1400715661890727,-0.2444219661439481],"type":1,"volume":0.034838045457373304},{"fixed":false,"mass":0.04155395449464261,"nu":0,"particle_id":305,"point":[0.2083987429016033,0.3191937298527597,0.005760947279249168],"type":1,"volume":0.04155395449464261},{"fixed":false,"mass":0.03913883011427364,"nu":0,"particle_id":306,"point":[0.5361023210272371,0.02131892417865922,0.04943608176889605],"type":1,"volume":0.03913883011427364},{"fixed":false,"mass":0.040205054380362544,"nu":0,"particle_id":307,"point":[4.585145896611925,-0.09887219175157656,-0.03820606121951187],"type":1,"volume":0.040205054380362544},{"fixed":false,"mass":0.03485450349323851,"nu":0,"particle_id":308,"point":[4.314233451172206,-0.1345956692580633,-0.2037649898648881],"type":1,"volume":0.03485450349323851},{"fixed":false,"mass":0.0405465157527426,"nu":0,"particle_id":309,"point":[4.690446860841035,0.03137257093361137,-0.3342867086050328],"type":1,"volume":0.0405465157527426},{"fixed":false,"mass":0.04109690470815112,"nu":0,"particle_id":310,"point":[4.508464180579515,-0.2334731699170505,-0.4373825029302116],"type":1,"volume":0.04109690470815112},{"fixed":false,"mass":0.03803992530278079,"nu":0,"particle_id":311,"point":[0.5570757237958459,-0.1083475640350249,-0.4224459468757631],"type":1,"volume":0.03803992530278079},{"fixed":false,"mass":0.04956086576069051,"nu":0,"particle_id":312,"point":[0.747142901391881,0.1001585778732168,-0.6520264806568804],"type":1,"volume":0.04956086576069051},{"fixed":false,"mass":0.033312801606461356,"nu":0,"particle_id":313,"point":[0.8703640216531715,-0.1526190573867122,-0.3608695310141254],"type":1,"volume":0.033312801606461356},{"fixed":false,"mass":0.0382424824897758,"nu":0,"particle_id":314,"point":[0.7354043907382048,-0.3190995977528188,-0.6188114193398824],"type":1,"volume":0.0382424824897758},{"fixed":false,"mass":0.044331750336704945,"nu":0,"particle_id":315,"point":[1.950286630429806,0.5962102966710449,0.1818607547557189],"type":1,"volume":0.044331750336704945},{"fixed":false,"mass":0.017503953949638294,"nu":0,"particle_id":316,"point":[-2.459625541229079,0.9442279257631171,-0.3156037695520635],"type":1,"volume":0.017503953949638294},{"fixed":false,"mass":0.050042088308853996,"nu":0,"particle_id":317,"point":[-2.331828034996342,0.6263585724365436,-0.2107849042854773],"type":1,"volume":0.050042088308853996},{"fixed":false,"mass":0.04685726393157461,"nu":0,"particle_id":318,"point":[-4.318643377280324,-0.03721585132849892,-0.6734336720589975],"type":1,"volume":0.04685726393157461},{"fixed":false,"mass":0.02062489811624557,"nu":0,"particle_id":319,"point":[-2.775971894224293,-0.1406418867498619,0.9861479832032067],"type":1,"volume":0.02062489811624557},{"fixed":false,"mass":0.012736257790510037,"nu":0,"particle_id":320,"point":[-2.491567982740876,-0.122874237615914,0.9878979439007669],"type":1,"volume":0.012736257790510037},{"fixed":false,"mass":0.012732526270213929,"nu":0,"particle_id":321,"point":[-2.487426304122777,0.1620333051661782,0.9840411123835833],"type":1,"volume":0.012732526270213929},{"fixed":false,"mass":0.05217091744344,"nu":0,"particle_id":322,"point":[3.034865247795092,0.05111847672681612,0.3408437517252455],"type":1,"volume":0.05217091744344},{"fixed":false,"mass":0.04603226034249329,"nu":0,"particle_id":323,"point":[1.392642899986337,0.02594223683769051,-0.610495863305347],"type":1,"volume":0.04603226034249329},{"fixed":false,"mass":0.015094702065701376,"nu":0,"particle_id":324,"point":[3.841580470403831,0.9509856974164272,0.2933263819342138],"type":1,"volume":0.015094702065701376},{"fixed":false,"mass":0.044705132190868115,"nu":0,"particle_id":325,"point":[-1.727893218783428,0.07660112843950537,0.6329606405124966],"type":1,"volume":0.044705132190868115},{"fixed":false,"mass":0.0641943703725775,"nu":0,"particle_id":326,"point":[-1.911482224420938,-0.2148650664989057,0.4734562609665851],"type":1,"volume":0.0641943703725775},{"fixed":false,"mass":0.039408509014700076,"nu":0,"particle_id":327,"point":[-1.51431670758116,-0.2792571772671046,0.63874613481934],"type":1,"volume":0.039408509014700076},{"fixed":false,"mass":0.026310975436162776,"nu":0,"particle_id":328,"point":[-1.712143276096106,-0.3916383977681603,0.9190930037812916],"type":1,"volume":0.026310975436162776},{"fixed":false,"mass":0.04887845482535269,"nu":0,"particle_id":329,"point":[4.356458132099592,-0.547513193147888,-0.3433335058117309],"type":1,"volume":0.04887845482535269},{"fixed":false,"mass":0.04367299571527408,"nu":0,"particle_id":330,"point":[4.085196157355436,-0.3573049399097361,-0.1990769625206552],"type":1,"volume":0.04367299571527408},{"fixed":false,"mass":0.0636243158859831,"nu":0,"particle_id":331,"point":[4.489546188333659,-0.5381907892672536,-0.007516813406451939],"type":1,"volume":0.0636243158859831},{"fixed":false,"mass":0.035991860167817934,"nu":0,"particle_id":332,"point":[0.03738686014610853,0.5642790532197781,0.3560629448646393],"type":1,"volume":0.035991860167817934},{"fixed":false,"mass":0.036926800996912666,"nu":0,"particle_id":333,"point":[0.4072064387094109,0.3976305747268796,0.5664986690901241],"type":1,"volume":0.036926800996912666},{"fixed":false,"mass":0.06385701873800281,"nu":0,"particle_id":334,"point":[0.3515777967235877,0.4926195980447557,0.2380324931369928],"type":1,"volume":0.06385701873800281},{"fixed":false,"mass":0.03670984583469253,"nu":0,"particle_id":335,"point":[4.740171750404889,0.6876794865911354,0.02087165044012332],"type":1,"volume":0.03670984583469253},{"fixed":false,"mass":0.010298521272634505,"nu":0,"particle_id":336,"point":[5,0.9853602136405565,0.1486402453456225],"type":2,"volume":0.010298521272634505},{"fixed":false,"mass":0.009419268015331406,"nu":0,"particle_id":337,"point":[5,0.9853602136405567,-0.1486402453456203],"type":2,"volume":0.009419268015331406},{"fixed":false,"mass":0.042965598805804237,"nu":0,"particle_id":338,"point":[-3.710210700033557,0.2784459913099164,-0.5884139261818745],"type":1,"volume":0.042965598805804237},{"fixed":false,"mass":0.047788826743932575,"nu":0,"particle_id":339,"point":[-3.580522817122302,0.3343942818497538,-0.2489426082059625],"type":1,"volume":0.047788826743932575},{"fixed":false,"mass":0.03743291154431926,"nu":0,"particle_id":340,"point":[-3.250467323690525,0.3757941972740365,-0.5900663434293696],"type":1,"volume":0.03743291154431926},{"fixed":false,"mass":0.03090825032262339,"nu":0,"particle_id":341,"point":[-3.638148916256764,0.5680580992020869,-0.4645562622237233],"type":1,"volume":0.03090825032262339},{"fixed":false,"mass":0.01839384261228336,"nu":0,"particle_id":342,"point":[-5,-0.2025311025647999,0.2296650809018178],"type":3,"volume":0.01839384261228336},{"fixed":false,"mass":0.04940409616036986,"nu":0,"particle_id":343,"point":[-4.672852058809136,0.0460226436994011,0.3005205265808617],"type":1,"volume":0.04940409616036986},{"fixed":false,"mass":0.006315179623792932,"nu":0,"particle_id":344,"point":[-5,0.125370815588424,0.2522376120795907],"type":3,"volume":0.006315179623792932},{"fixed":false,"mass":0.01902573833844286,"nu":0,"particle_id":345,"point":[-5,-0.05382270361391531,0.4725068506284891],"type":3,"volume":0.01902573833844286},{"fixed":false,"mass":0.028569052229710203,"nu":0,"particle_id":346,"point":[3.900797496534923,-0.09523261260998354,0.9906204063386734],"type":1,"volume":0.028569052229710203},{"fixed":false,"mass":0.057461352614976605,"nu":0,"particle_id":347,"point":[4.133395722285912,-0.3647562975157106,0.5337670178919192],"type":1,"volume":0.057461352614976605},{"fixed":false,"mass":0.06036871369242387,"nu":0,"particle_id":348,"point":[4.175212820912298,0.05596745584691704,0.5839667438079432],"type":1,"volume":0.06036871369242387},{"fixed":false,"mass":0.02301461728624142,"nu":0,"particle_id":349,"point":[4.236222097531536,-0.1804358469864153,0.9822286202143693],"type":1,"volume":0.02301461728624142},{"fixed":false,"mass":0.0450064670208678,"nu":0,"particle_id":350,"point":[1.341499219372383,-0.3618337356917706,-0.5414755908182005],"type":1,"volume":0.0450064670208678},{"fixed":false,"mass":0.023884981639067746,"nu":0,"particle_id":351,"point":[1.545016859397928,-0.2661613159416563,-0.959226130095244],"type":1,"volume":0.023884981639067746},{"fixed":false,"mass":0.011566405153186776,"nu":0,"particle_id":352,"point":[1.729320319362443,0.5843426770600588,-0.8078566777182377],"type":1,"volume":0.011566405153186776},{"fixed":false,"mass":0.019363235853521222,"nu":0,"particle_id":353,"point":[1.708941597493081,0.787452600965811,-0.6092051165192587],"type":1,"volume":0.019363235853521222},{"fixed":false,"mass":0.03991609829760075,"nu":0,"particle_id":354,"point":[1.579261957549237,0.3204408656479726,-0.6347074933951168],"type":1,"volume":0.03991609829760075},{"fixed":false,"mass":0.03831143393800186,"nu":0,"particle_id":355,"point":[1.938088268539215,0.4694292280994222,-0.5340558335654607],"type":1,"volume":0.03831143393800186},{"fixed":false,"mass":0.04001281013677298,"nu":0,"particle_id":356,"point":[-4.447057404060107,-0.3549381497400995,0.2057938865047611],"type":1,"volume":0.04001281013677298},{"fixed":false,"mass":0.04590787568875264,"nu":0,"particle_id":357,"point":[-4.589023769272549,-0.1547098918652496,0.5619252217939441],"type":1,"volume":0.04590787568875264},{"fixed":false,"mass":0.03745264442923401,"nu":0,"particle_id":358,"point":[-4.721797974124273,-0.2866258227502707,0.02074317021649211],"type":1,"volume":0.03745264442923401},{"fixed":false,"mass":0.014151267695869857,"nu":0,"particle_id":359,"point":[-5,-0.4567777755027361,-0.8842752809932557],"type":3,"volume":0.014151267695869857},{"fixed":false,"mass":0.012138588018936605,"nu":0,"particle_id":360,"point":[-4.662319157509547,-0.1448229636338084,-0.9857361830733626],"type":1,"volume":0.012138588018936605},{"fixed":false,"mass":0.052855701808392046,"nu":0,"particle_id":361,"point":[-4.697544488685924,-0.3699699232032009,-0.527921882709032],"type":1,"volume":0.052855701808392046},{"fixed":false,"mass":0.025055018753701783,"nu":0,"particle_id":362,"point":[-4.536230404242893,-0.3199634103958382,-0.942905443171439],"type":1,"volume":0.025055018753701783},{"fixed":false,"mass":0.025393376044373632,"nu":0,"particle_id":363,"point":[5,0,0],"type":2,"volume":0.025393376044373632},{"fixed":false,"mass":0.021378411499744357,"nu":0,"particle_id":364,"point":[5,0.03902474269705655,-0.4684806111251374],"type":2,"volume":0.021378411499744357},{"fixed":false,"mass":0.03113921631174114,"nu":0,"particle_id":365,"point":[5,-0.4207833844029978,-0.2104427790538431],"type":2,"volume":0.03113921631174114},{"fixed":false,"mass":0.01543743867839918,"nu":0,"particle_id":366,"point":[2.206637845530393,0.5997176210975868,-0.7952387872364595],"type":1,"volume":0.01543743867839918},{"fixed":false,"mass":0.028590355143681755,"nu":0,"particle_id":367,"point":[1.931949365334744,0.3452190592570977,-0.9352442258470243],"type":1,"volume":0.028590355143681755},{"fixed":false,"mass":0.018267611636915187,"nu":0,"particle_id":368,"point":[2.258507045259502,0.2605619925546478,-0.9609246662751385],"type":1,"volume":0.018267611636915187},{"fixed":false,"mass":0.060260346730540024,"nu":0,"particle_id":369,"point":[2.253935410917276,0.30121671137991,-0.473218415106275],"type":1,"volume":0.060260346730540024},{"fixed":false,"mass":0.06398977387639924,"nu":0,"particle_id":370,"point":[2.73206029191555,-0.3967816953683554,0.2376549984105568],"type":1,"volume":0.06398977387639924},{"fixed":false,"mass":0.02088828007760897,"nu":0,"particle_id":371,"point":[-2.978643579717544,-0.9933051418021752,-0.06797403600339623],"type":1,"volume":0.02088828007760897},{"fixed":false,"mass":0.047590155802448846,"nu":0,"particle_id":372,"point":[-2.814006496248484,-0.4880689856103418,-0.148249113898269],"type":1,"volume":0.047590155802448846},{"fixed":false,"mass":0.022828969093572883,"nu":0,"particle_id":373,"point":[-2.791504694226523,-0.9801273813678559,0.1972591244818448],"type":1,"volume":0.022828969093572883},{"fixed":false,"mass":0.012603960230614471,"nu":0,"particle_id":374,"point":[-2.627666658230266,-0.9932265612354176,-0.06877187788683975],"type":1,"volume":0.012603960230614471},{"fixed":false,"mass":0.043037198380388636,"nu":0,"particle_id":375,"point":[0.9115676193396726,-0.002685776811705065,-0.07851611311025196],"type":1,"volume":0.043037198380388636},{"fixed":false,"mass":0.006717422415061768,"nu":0,"particle_id":376,"point":[-0.532065219844697,-0.4860992365044338,0.8686026335655014],"type":1,"volume":0.006717422415061768},{"fixed":false,"mass":0.016383203778620233,"nu":0,"particle_id":377,"point":[-0.5675407935454168,-0.7189036570879586,0.6927322463097543],"type":1,"volume":0.016383203778620233},{"fixed":false,"mass":0.05118925612109336,"nu":0,"particle_id":378,"point":[-0.5571060165041304,-0.2261067849269963,0.6234987577396465],"type":1,"volume":0.05118925612109336},{"fixed":false,"mass":0.03735022778530657,"nu":0,"particle_id":379,"point":[-2.564318858102155,0.4073797660171691,0.5488586962292776],"type":1,"volume":0.03735022778530657},{"fixed":false,"mass":0.027168730888564564,"nu":0,"particle_id":380,"point":[-4.428801278961851,0.7242735657018197,-0.1914555925305861],"type":1,"volume":0.027168730888564564},{"fixed":false,"mass":0.02198796520611299,"nu":0,"particle_id":381,"point":[-4.226881956461579,0.9194390652769016,-0.3909909622474873],"type":1,"volume":0.02198796520611299},{"fixed":false,"mass":0.014038881880449145,"nu":0,"particle_id":382,"point":[-4.208695566218871,0.992190978688664,-0.07928632393446365],"type":1,"volume":0.014038881880449145},{"fixed":false,"mass":0.08081085863473943,"nu":0,"particle_id":383,"point":[-4.004191517833799,0.5167772998588582,-0.3109854597287717],"type":1,"volume":0.08081085863473943},{"fixed":false,"mass":0.022508986917946172,"nu":0,"particle_id":384,"point":[-4.30784382452293,-0.8444285917881262,0.531325687651002],"type":1,"volume":0.022508986917946172},{"fixed":false,"mass":0.04747993325049497,"nu":0,"particle_id":385,"point":[-4.320655369665823,-0.6822850910370645,0.03555777760854781],"type":1,"volume":0.04747993325049497},{"fixed":false,"mass":0.061002608115571025,"nu":0,"particle_id":386,"point":[2.809098614311496,0.6697693849743858,0.04900032804593518],"type":1,"volume":0.061002608115571025},{"fixed":false,"mass":0.016834791916597126,"nu":0,"particle_id":387,"point":[2.785369587020907,0.9455884881606803,0.3111185964116037],"type":1,"volume":0.016834791916597126},{"fixed":false,"mass":0.01664624452123678,"nu":0,"particle_id":388,"point":[5,-0.5632090774271223,0.1044213632569307],"type":2,"volume":0.01664624452123678},{"fixed":false,"mass":0.03615096975852365,"nu":0,"particle_id":389,"point":[4.710524433397111,-0.6827536531471426,0.175116848553858],"type":1,"volume":0.03615096975852365},{"fixed":false,"mass":0.019945963716831466,"nu":0,"particle_id":390,"point":[5,-0.6466551408589429,-0.1183660943684787],"type":2,"volume":0.019945963716831466},{"fixed":false,"mass":0.010063866878470247,"nu":0,"particle_id":391,"point":[5,-1,0],"type":2,"volume":0.010063866878470247},{"fixed":false,"mass":0.03983312200929016,"nu":0,"particle_id":392,"point":[-4.560494651543501,0.008088466152775614,-0.01821127109030518],"type":1,"volume":0.03983312200929016},{"fixed":false,"mass":0.03685204908719612,"nu":0,"particle_id":393,"point":[-4.414031791449537,-0.2134100472394244,-0.3708040713153998],"type":1,"volume":0.03685204908719612},{"fixed":false,"mass":0.034323730602822365,"nu":0,"particle_id":394,"point":[-4.710155728110451,-0.08499596702793961,-0.2981915982054573],"type":1,"volume":0.034323730602822365},{"fixed":false,"mass":0.0640019219262844,"nu":0,"particle_id":395,"point":[0.02745076152495485,-0.2299890358911523,-0.4616266466204063],"type":1,"volume":0.0640019219262844},{"fixed":false,"mass":0.05969337362106137,"nu":0,"particle_id":396,"point":[-0.0951137418732172,-0.6067743331965254,-0.1726837287867926],"type":1,"volume":0.05969337362106137},{"fixed":false,"mass":0.05585581496050277,"nu":0,"particle_id":397,"point":[0.3111163298532363,-0.491082020812833,-0.1233598119262933],"type":1,"volume":0.05585581496050277},{"fixed":false,"mass":0.03937953826292331,"nu":0,"particle_id":398,"point":[4.477918636093202,-0.5265984523543372,0.4126456031989938],"type":1,"volume":0.03937953826292331},{"fixed":false,"mass":0.022598574110272232,"nu":0,"particle_id":399,"point":[4.311753942760346,-0.9826362757372568,0.1762968510030892],"type":1,"volume":0.022598574110272232},{"fixed":false,"mass":0.05950767006695242,"nu":0,"particle_id":400,"point":[2.278442841614884,-0.2354276625793917,0.4302086442113305],"type":1,"volume":0.05950767006695242},{"fixed":false,"mass":0.04106757605877499,"nu":0,"particle_id":401,"point":[2.322088034782306,-0.2631172838300679,-0.1640639023130168],"type":1,"volume":0.04106757605877499},{"fixed":false,"mass":0.06298627608632108,"nu":0,"particle_id":402,"point":[1.077347378240315,-0.3897389378410603,-0.2913480949132416],"type":1,"volume":0.06298627608632108},{"fixed":false,"mass":0.053482503683237016,"nu":0,"particle_id":403,"point":[0.6730289080436134,-0.5107944633950288,-0.3465260734420292],"type":1,"volume":0.053482503683237016},{"fixed":false,"mass":0.03972139538581521,"nu":0,"particle_id":404,"point":[1.768993225991768,0.6148119132803592,-0.1638673074320256],"type":1,"volume":0.03972139538581521},{"fixed":false,"mass":0.022800924022012798,"nu":0,"particle_id":405,"point":[1.655539738970316,0.9284683195155594,-0.3675562288970853],"type":1,"volume":0.022800924022012798},{"fixed":false,"mass":0.01611249513626628,"nu":0,"particle_id":406,"point":[1.980052879430746,0.9808808313846238,-0.194120176621338],"type":1,"volume":0.01611249513626628},{"fixed":false,"mass":0.03515769008064742,"nu":0,"particle_id":407,"point":[2.071424584289844,0.6759928660377171,-0.2797713635104553],"type":1,"volume":0.03515769008064742},{"fixed":false,"mass":0.016132613690641923,"nu":0,"particle_id":408,"point":[-0.6446894350648051,0.7887943560607247,0.6075701832056308],"type":1,"volume":0.016132613690641923},{"fixed":false,"mass":0.03231949329304842,"nu":0,"particle_id":409,"point":[-0.43192826830179,0.3342100765756691,0.6545802802801486],"type":1,"volume":0.03231949329304842},{"fixed":false,"mass":0.02012489832079343,"nu":0,"particle_id":410,"point":[-3.754867118730866,0.8685921403455626,-0.4861188679381553],"type":1,"volume":0.02012489832079343},{"fixed":false,"mass":0.016800027295851564,"nu":0,"particle_id":411,"point":[-3.300417531599843,0.943398894405177,-0.3183367196805481],"type":1,"volume":0.016800027295851564},{"fixed":false,"mass":0.037453292819736535,"nu":0,"particle_id":412,"point":[-1.112522089823344,0.3017013345375487,-0.5780981499053093],"type":1,"volume":0.037453292819736535},{"fixed":false,"mass":0.047313585348425884,"nu":0,"particle_id":413,"point":[-0.6115882585308059,0.3229258699490731,-0.600023484864719],"type":1,"volume":0.047313585348425884},{"fixed":false,"mass":0.03335603056923039,"nu":0,"particle_id":414,"point":[-2.978154521992757,0.003051322278755264,-0.004480898597038346],"type":1,"volume":0.03335603056923039},{"fixed":false,"mass":0.0606546404749683,"nu":0,"particle_id":415,"point":[-3.37321737107582,-0.08400421395439206,0.06860040149971734],"type":1,"volume":0.0606546404749683},{"fixed":false,"mass":0.04557886919987062,"nu":0,"particle_id":416,"point":[-3.242103227665906,0.1492752713496223,-0.24482126053117],"type":1,"volume":0.04557886919987062},{"fixed":false,"mass":0.039944307847752845,"nu":0,"particle_id":417,"point":[1.259662873253521,0.1510037883509702,0.2868813288780193],"type":1,"volume":0.039944307847752845},{"fixed":false,"mass":0.01819271541205241,"nu":0,"particle_id":418,"point":[-3.613068757098153,0.2531687027522975,-0.963167396217629],"type":1,"volume":0.01819271541205241},{"fixed":false,"mass":0.022870917992108584,"nu":0,"particle_id":419,"point":[-3.133923347589175,0.2267399593462462,-0.971184467881764],"type":1,"volume":0.022870917992108584},{"fixed":false,"mass":0.05889029145590221,"nu":0,"particle_id":420,"point":[-3.398673230577943,0.0831847652997855,-0.5911328706184457],"type":1,"volume":0.05889029145590221},{"fixed":false,"mass":0.017500497670000666,"nu":0,"particle_id":421,"point":[-3.585985467785876,-0.09412675486283326,-0.9907293238201038],"type":1,"volume":0.017500497670000666},{"fixed":false,"mass":0.052421519794763345,"nu":0,"particle_id":422,"point":[-3.520331713290353,-0.1031247569727718,0.5847785547018767],"type":1,"volume":0.052421519794763345},{"fixed":false,"mass":0.027717620711845792,"nu":0,"particle_id":423,"point":[-3.851719561803271,0.000519572404737601,0.9999488265847117],"type":1,"volume":0.027717620711845792},{"fixed":false,"mass":0.054696097829221066,"nu":0,"particle_id":424,"point":[-3.865055585669245,0.1938382381728525,0.5352766557450243],"type":1,"volume":0.054696097829221066},{"fixed":false,"mass":0.010198103823118329,"nu":0,"particle_id":425,"point":[0.5590431797597235,-0.4294312848916906,-0.8988922847540333],"type":1,"volume":0.010198103823118329},{"fixed":false,"mass":0.014098215057037915,"nu":0,"particle_id":426,"point":[0.6265019694669411,-0.6668448551387852,-0.740148889971858],"type":1,"volume":0.014098215057037915},{"fixed":false,"mass":0.023664874454881947,"nu":0,"particle_id":427,"point":[-0.03324676831345631,0.2788948494544816,0.9553634549335254],"type":1,"volume":0.023664874454881947},{"fixed":false,"mass":0.012378415472704223,"nu":0,"particle_id":428,"point":[2.428557509161417,-0.9699350137475129,-0.2308588576292035],"type":1,"volume":0.012378415472704223},{"fixed":false,"mass":0.04274203615830344,"nu":0,"particle_id":429,"point":[2.57468900653506,-0.683059316819491,-0.1174635100570868],"type":1,"volume":0.04274203615830344},{"fixed":false,"mass":0.014453711025124294,"nu":0,"particle_id":430,"point":[2.718160042761412,-0.9178845198448603,-0.3938993121909842],"type":1,"volume":0.014453711025124294},{"fixed":false,"mass":0.01941518489134874,"nu":0,"particle_id":431,"point":[2.378453105279212,-0.804057514410917,-0.5889719709443135],"type":1,"volume":0.01941518489134874},{"fixed":false,"mass":0.04071559297329217,"nu":0,"particle_id":432,"point":[3.447817049312609,-0.03522491705447164,-0.2792058208416099],"type":1,"volume":0.04071559297329217},{"fixed":false,"mass":0.044590031729158146,"nu":0,"particle_id":433,"point":[2.445730129791569,0.5863912580845965,-0.3732108356234886],"type":1,"volume":0.044590031729158146},{"fixed":false,"mass":0.015378274836822812,"nu":0,"particle_id":434,"point":[2.310244143749077,0.9315357944225086,-0.3574441193118698],"type":1,"volume":0.015378274836822812},{"fixed":false,"mass":0.02148076520845459,"nu":0,"particle_id":435,"point":[2.666796291042784,0.7273709403363537,-0.6824148318194327],"type":1,"volume":0.02148076520845459},{"fixed":false,"mass":0.04133782056293413,"nu":0,"particle_id":436,"point":[-4.69524177783212,0.2373800521041662,-0.2202644004813641],"type":1,"volume":0.04133782056293413},{"fixed":false,"mass":0.020324137775081602,"nu":0,"particle_id":437,"point":[-5,0.1616044704709591,-0.5700737751341308],"type":3,"volume":0.020324137775081602},{"fixed":false,"mass":0.04061680154459365,"nu":0,"particle_id":438,"point":[-4.548862035365133,0.1961379378517809,-0.5176344486287131],"type":1,"volume":0.04061680154459365},{"fixed":false,"mass":0.04735345134923272,"nu":0,"particle_id":439,"point":[-0.3388416081805412,0.6648127596524501,0.120505255187447],"type":1,"volume":0.04735345134923272},{"fixed":false,"mass":0.013953659269746517,"nu":0,"particle_id":440,"point":[-0.5452479977520281,0.9904632078045408,-0.09682867611171558],"type":1,"volume":0.013953659269746517},{"fixed":false,"mass":0.017808636466926018,"nu":0,"particle_id":441,"point":[-0.4426534452573045,0.9321214446481869,-0.3555134892528439],"type":1,"volume":0.017808636466926018},{"fixed":false,"mass":0.027879144026445857,"nu":0,"particle_id":442,"point":[-1.219999225300293,-0.9826473817962202,-0.1761840892940956],"type":1,"volume":0.027879144026445857},{"fixed":false,"mass":0.05575955248580224,"nu":0,"particle_id":443,"point":[-1.154730006596523,-0.5793295932242937,-0.2755252568805653],"type":1,"volume":0.05575955248580224},{"fixed":false,"mass":0.07801429770920942,"nu":0,"particle_id":444,"point":[-0.9447288133045737,-0.5139965262822277,0.04571164722727455],"type":1,"volume":0.07801429770920942},{"fixed":false,"mass":0.025081747484748063,"nu":0,"particle_id":445,"point":[-0.8053909985425183,-0.9829296246531509,-0.1733184294769953],"type":1,"volume":0.025081747484748063},{"fixed":false,"mass":0.017937456587034387,"nu":0,"particle_id":446,"point":[3.994853660083982,0.1049011164055397,-0.989668141831485],"type":1,"volume":0.017937456587034387},{"fixed":false,"mass":0.03247094719903049,"nu":0,"particle_id":447,"point":[3.997985655144568,0.2633370796371267,-0.6911693397018224],"type":1,"volume":0.03247094719903049},{"fixed":false,"mass":0.06040415250259707,"nu":0,"particle_id":448,"point":[4.207439147045226,0.01554936484689754,-0.5965977697630661],"type":1,"volume":0.06040415250259707},{"fixed":false,"mass":0.01438168143433031,"nu":0,"particle_id":449,"point":[2.263606934511956,0.7950919105072195,-0.5998965909099947],"type":1,"volume":0.01438168143433031},{"fixed":false,"mass":0.017759452248747004,"nu":0,"particle_id":450,"point":[2.816199481080052,-0.2284475039513554,-0.9706664898886925],"type":1,"volume":0.017759452248747004},{"fixed":false,"mass":0.0299842589861546,"nu":0,"particle_id":451,"point":[3.229861540020519,0.08410408032684925,-0.9917164711005448],"type":1,"volume":0.0299842589861546},{"fixed":false,"mass":0.029785228345060564,"nu":0,"particle_id":452,"point":[3.075442681567607,-0.01455403286748605,-0.6897068353124263],"type":1,"volume":0.029785228345060564},{"fixed":false,"mass":0.027996037004204822,"nu":0,"particle_id":453,"point":[3.189825676412912,-0.409731831999987,-0.9094218616967864],"type":1,"volume":0.027996037004204822},{"fixed":false,"mass":0.025208814309946814,"nu":0,"particle_id":454,"point":[-2.036281963727589,-0.6088537639615936,0.7877409485579903],"type":1,"volume":0.025208814309946814},{"fixed":false,"mass":0.017562275302873673,"nu":0,"particle_id":455,"point":[-1.695935859263936,-0.7200993717854909,0.691275263735214],"type":1,"volume":0.017562275302873673},{"fixed":false,"mass":0.0406420791798831,"nu":0,"particle_id":456,"point":[-2.811993666109769,-0.2597511634454077,0.07854231117968707],"type":1,"volume":0.0406420791798831},{"fixed":false,"mass":0.04571252931514123,"nu":0,"particle_id":457,"point":[-2.572743561714617,-0.05376914495645748,0.01610654019603835],"type":1,"volume":0.04571252931514123},{"fixed":false,"mass":0.039631962286871374,"nu":0,"particle_id":458,"point":[3.022141045749324,0.2569636609926702,-0.2287952446625661],"type":1,"volume":0.039631962286871374},{"fixed":false,"mass":0.04179941052260108,"nu":0,"particle_id":459,"point":[3.255614924914051,-0.0272716946151466,0.01399139804825961],"type":1,"volume":0.04179941052260108},{"fixed":false,"mass":0.02281794265844556,"nu":0,"particle_id":460,"point":[3.368884562017886,-0.9200539089285176,-0.3898406706814885],"type":1,"volume":0.02281794265844556},{"fixed":false,"mass":0.010285199633551413,"nu":0,"particle_id":461,"point":[3.26357138698309,-0.9851749209552969,-0.1505215535506417],"type":1,"volume":0.010285199633551413},{"fixed":false,"mass":0.052458738232886624,"nu":0,"particle_id":462,"point":[4.541206227887655,0.2039009937173035,-0.5829850841061374],"type":1,"volume":0.052458738232886624},{"fixed":false,"mass":0.03224983897490185,"nu":0,"particle_id":463,"point":[3.80168239016323,-0.1867425074350222,-0.2333090093059733],"type":1,"volume":0.03224983897490185},{"fixed":false,"mass":0.05533600753447479,"nu":0,"particle_id":464,"point":[4.062766087814739,-0.03731500437118657,0.05991677350780944],"type":1,"volume":0.05533600753447479},{"fixed":false,"mass":0.034914452075423374,"nu":0,"particle_id":465,"point":[3.65656083354117,0.0003531149005125966,0.0003111835130313878],"type":1,"volume":0.034914452075423374},{"fixed":false,"mass":0.016919385544027447,"nu":0,"particle_id":466,"point":[2.893397203498036,0.774352838682328,0.6251672230460473],"type":1,"volume":0.016919385544027447},{"fixed":false,"mass":0.06575598251780737,"nu":0,"particle_id":467,"point":[3.02078432439836,0.4913851656163602,0.3111328545639421],"type":1,"volume":0.06575598251780737},{"fixed":false,"mass":0.014859386991627425,"nu":0,"particle_id":468,"point":[2.637270369251912,0.8453116323520437,0.5296736349536404],"type":1,"volume":0.014859386991627425},{"fixed":false,"mass":0.013876176885519875,"nu":0,"particle_id":469,"point":[2.97806001000529,0.8113861621566576,-0.5800419878283367],"type":1,"volume":0.013876176885519875},{"fixed":false,"mass":0.06174049086691122,"nu":0,"particle_id":470,"point":[0.7068104481280483,-0.2243531098636304,0.5752048577472375],"type":1,"volume":0.06174049086691122},{"fixed":false,"mass":0.04959060131929213,"nu":0,"particle_id":471,"point":[0.7772684143886415,0.1710226405681259,0.6355389761459849],"type":1,"volume":0.04959060131929213},{"fixed":false,"mass":0.043232796894229694,"nu":0,"particle_id":472,"point":[0.8003952306630803,0.131330301988912,0.2531303667538218],"type":1,"volume":0.043232796894229694},{"fixed":false,"mass":0.012209413875634787,"nu":0,"particle_id":473,"point":[-0.2224177716256706,-0.8719936376773831,-0.4797551140272662],"type":1,"volume":0.012209413875634787},{"fixed":false,"mass":0.018954974705104474,"nu":0,"particle_id":474,"point":[-0.1280590308114988,-0.7000458525898701,-0.7129015355293963],"type":1,"volume":0.018954974705104474},{"fixed":false,"mass":0.06476475167987937,"nu":0,"particle_id":475,"point":[-2.905801082478374,-0.5028141966058933,0.2674548847084701],"type":1,"volume":0.06476475167987937},{"fixed":false,"mass":0.056441690567067444,"nu":0,"particle_id":476,"point":[-0.3929927291104882,0.5621294743796047,-0.2011320872011412],"type":1,"volume":0.056441690567067444},{"fixed":false,"mass":0.0479433544440213,"nu":0,"particle_id":477,"point":[-1.651768059945895,-0.4899939981822175,0.379793677962541],"type":1,"volume":0.0479433544440213},{"fixed":false,"mass":0.015306320962243578,"nu":0,"particle_id":478,"point":[4.374144617168078,0.9999999999999999,1.169138000865524e-15],"type":1,"volume":0.015306320962243578},{"fixed":false,"mass":0.017351920375610824,"nu":0,"particle_id":479,"point":[4.208742164198657,0.9576523213241108,-0.2713494681654346],"type":1,"volume":0.017351920375610824},{"fixed":false,"mass":0.04937110999067572,"nu":0,"particle_id":480,"point":[1.016920108016674,-0.415383297645586,0.4031391964212584],"type":1,"volume":0.04937110999067572},{"fixed":false,"mass":0.021273832654346424,"nu":0,"particle_id":481,"point":[0.6947391947538961,-0.5296134437959139,0.8453438051961342],"type":1,"volume":0.021273832654346424},{"fixed":false,"mass":0.04676399282005567,"nu":0,"particle_id":482,"point":[0.677153210482357,-0.5272583385963083,0.3936744912652289],"type":1,"volume":0.04676399282005567},{"fixed":false,"mass":0.015675498797122055,"nu":0,"particle_id":483,"point":[-4.339812456980797,0.2666893534725878,-0.9590659516614156],"type":1,"volume":0.015675498797122055},{"fixed":false,"mass":0.021230337076012632,"nu":0,"particle_id":484,"point":[3.894480192339681,0.9760602252411635,-0.2106667413983267],"type":1,"volume":0.021230337076012632},{"fixed":false,"mass":0.022647585544825936,"nu":0,"particle_id":485,"point":[3.956212664494338,0.8747881983152965,-0.4745268588049645],"type":1,"volume":0.022647585544825936},{"fixed":false,"mass":0.0103619045027685,"nu":0,"particle_id":486,"point":[2.033257175151563,-0.8827227190891273,-0.4596824145265175],"type":1,"volume":0.0103619045027685},{"fixed":false,"mass":0.013785296565029257,"nu":0,"particle_id":487,"point":[1.915577848510047,-0.9637153781564272,-0.2513622483936021],"type":1,"volume":0.013785296565029257},{"fixed":false,"mass":0.0526666798273384,"nu":0,"particle_id":488,"point":[1.343806725991137,-0.5040878158955332,0.1560164103242782],"type":1,"volume":0.0526666798273384},{"fixed":false,"mass":0.03986640602988994,"nu":0,"particle_id":489,"point":[1.082556841624721,-0.2717264821200776,0.0827164948580461],"type":1,"volume":0.03986640602988994},{"fixed":false,"mass":0.017640490989158836,"nu":0,"particle_id":490,"point":[-1.733956741602771,0.2749672353890485,0.956554883634764],"type":1,"volume":0.017640490989158836},{"fixed":false,"mass":0.02766498864293735,"nu":0,"particle_id":491,"point":[-1.361128442225207,-0.01066218867345667,0.7303852617724089],"type":1,"volume":0.02766498864293735},{"fixed":false,"mass":0.04955210910827252,"nu":0,"particle_id":492,"point":[-1.333790166875309,0.2942130838296303,0.6288405472562405],"type":1,"volume":0.04955210910827252},{"fixed":false,"mass":0.01797528158309501,"nu":0,"particle_id":493,"point":[-1.250869283970371,0.1539771342692995,0.9848345759609021],"type":1,"volume":0.01797528158309501},{"fixed":false,"mass":0.04396279092442496,"nu":0,"particle_id":494,"point":[-2.265391081355599,0.1529744002049249,-0.09036430898252702],"type":1,"volume":0.04396279092442496},{"fixed":false,"mass":0.050163322760476615,"nu":0,"particle_id":495,"point":[-2.241956820158258,0.3502363453955511,-0.4206415300488416],"type":1,"volume":0.050163322760476615},{"fixed":false,"mass":0.02575167093917805,"nu":0,"particle_id":496,"point":[-3.136783277752716,-0.2179694508519731,-0.9738449725470518],"type":1,"volume":0.02575167093917805},{"fixed":false,"mass":0.011309970724868636,"nu":0,"particle_id":497,"point":[-1.818439024254243,0.8537461153983048,-0.5138938270526173],"type":1,"volume":0.011309970724868636},{"fixed":false,"mass":0.03058736042521498,"nu":0,"particle_id":498,"point":[-2.15277942812303,0.9835426051258265,-0.1670947342936451],"type":1,"volume":0.03058736042521498},{"fixed":false,"mass":0.019010372374075202,"nu":0,"particle_id":499,"point":[-1.604268590324133,0.9496530354622581,-0.2977195796389685],"type":1,"volume":0.019010372374075202},{"fixed":false,"mass":0.016726673390743213,"nu":0,"particle_id":500,"point":[-1.647326914844132,0.9985606180271498,0.01461429042319919],"type":1,"volume":0.016726673390743213},{"fixed":false,"mass":0.009394243066383966,"nu":0,"particle_id":501,"point":[4.628890088155206,-0.2221001761570721,0.9725919307248572],"type":1,"volume":0.009394243066383966},{"fixed":false,"mass":0.024225132274510133,"nu":0,"particle_id":502,"point":[4.725482602881272,0.4310094934322792,-0.593136176883271],"type":1,"volume":0.024225132274510133},{"fixed":false,"mass":0.012223032328162938,"nu":0,"particle_id":503,"point":[2.286425764327157,0.6029019107182447,0.7926255082809313],"type":1,"volume":0.012223032328162938},{"fixed":false,"mass":0.01155763341512236,"nu":0,"particle_id":504,"point":[1.99102013065114,0.7001603885336615,0.7128075383095391],"type":1,"volume":0.01155763341512236},{"fixed":false,"mass":0.022173131698950115,"nu":0,"particle_id":505,"point":[2.355538214395486,0.8360967737307315,0.5469134228673583],"type":1,"volume":0.022173131698950115},{"fixed":false,"mass":0.039717707005458416,"nu":0,"particle_id":506,"point":[2.093154478320526,0.5190312617317041,0.46392629141071],"type":1,"volume":0.039717707005458416},{"fixed":false,"mass":0.013712349347936487,"nu":0,"particle_id":507,"point":[3.761473751494503,-0.9936496245037812,-0.06447644443840522],"type":1,"volume":0.013712349347936487},{"fixed":false,"mass":0.021052332299175268,"nu":0,"particle_id":508,"point":[3.912747963489887,-0.9828092080243522,0.1745410400266875],"type":1,"volume":0.021052332299175268},{"fixed":false,"mass":0.017931885420643327,"nu":0,"particle_id":509,"point":[-4.636204077663011,0.2666893534725878,-0.9590659516614157],"type":1,"volume":0.017931885420643327},{"fixed":false,"mass":0.016863290479398642,"nu":0,"particle_id":510,"point":[-4.488008267321904,0.5236851615008375,-0.8485125380999123],"type":1,"volume":0.016863290479398642},{"fixed":false,"mass":0.03214756883806146,"nu":0,"particle_id":511,"point":[0.4070381010421754,0.4996203715376544,-0.8613754363195506],"type":1,"volume":0.03214756883806146},{"fixed":false,"mass":0.01990353144872357,"nu":0,"particle_id":512,"point":[-0.1335097133684486,0.5692272680561492,-0.8202615733024472],"type":1,"volume":0.01990353144872357},{"fixed":false,"mass":0.022684281330445095,"nu":0,"particle_id":513,"point":[0.1966229918873446,0.2200803258148279,-0.97320464562756],"type":1,"volume":0.022684281330445095},{"fixed":false,"mass":0.06240784515583585,"nu":0,"particle_id":514,"point":[0.1311188848607186,0.2918113072550412,-0.4470501441594271],"type":1,"volume":0.06240784515583585},{"fixed":false,"mass":0.008513978417893323,"nu":0,"particle_id":515,"point":[-0.7308740232373951,-0.005608721072547262,-0.9994475891905259],"type":1,"volume":0.008513978417893323},{"fixed":false,"mass":0.02915552623996763,"nu":0,"particle_id":516,"point":[-0.5450983353557908,0.03870052886645936,-0.7387364160036708],"type":1,"volume":0.02915552623996763},{"fixed":false,"mass":0.01203006386780243,"nu":0,"particle_id":517,"point":[-0.6622708853378605,0.2689253571207114,-0.9583876673702234],"type":1,"volume":0.01203006386780243},{"fixed":false,"mass":0.04979248604473674,"nu":0,"particle_id":518,"point":[0.003929497586142593,-0.1814487657022003,0.571319202999107],"type":1,"volume":0.04979248604473674},{"fixed":false,"mass":0.047280593972269185,"nu":0,"particle_id":519,"point":[0.2403192462736594,0.06543553492009882,0.6820598034411298],"type":1,"volume":0.047280593972269185},{"fixed":false,"mass":0.04023988859568316,"nu":0,"particle_id":520,"point":[-0.2296568119078888,0.08210965018073563,0.6784961729714686],"type":1,"volume":0.04023988859568316},{"fixed":false,"mass":0.020961768636790327,"nu":0,"particle_id":521,"point":[-0.06602695259142422,-0.09493392728190987,0.9906498242757977],"type":1,"volume":0.020961768636790327},{"fixed":false,"mass":0.02120841971576497,"nu":0,"particle_id":522,"point":[-0.1711936368038592,0.2345240316616338,-0.9688231953599314],"type":1,"volume":0.02120841971576497},{"fixed":false,"mass":0.05346957087199773,"nu":0,"particle_id":523,"point":[-0.1846488820872028,0.04021294006929188,-0.6363033245293416],"type":1,"volume":0.05346957087199773},{"fixed":false,"mass":0.019542044866340525,"nu":0,"particle_id":524,"point":[-0.003618105374116314,-0.09652941896865216,-0.9904926820605258],"type":1,"volume":0.019542044866340525},{"fixed":false,"mass":0.04827320814187752,"nu":0,"particle_id":525,"point":[-0.7095973922532746,0.6716895887619997,-0.0957526663238627],"type":1,"volume":0.04827320814187752},{"fixed":false,"mass":0.013542010036038032,"nu":0,"particle_id":526,"point":[1.986410523639958,0.8282829495809576,-0.5594531927807165],"type":1,"volume":0.013542010036038032},{"fixed":false,"mass":0.044147265580980276,"nu":0,"particle_id":527,"point":[-2.547582594375717,-0.579079097423526,0.3919374798720334],"type":1,"volume":0.044147265580980276},{"fixed":false,"mass":0.017638096233961103,"nu":0,"particle_id":528,"point":[-2.707475554051676,-0.7159784671739545,0.6962966005329826],"type":1,"volume":0.017638096233961103},{"fixed":false,"mass":0.018511019721152055,"nu":0,"particle_id":529,"point":[-2.891202994743407,-0.8748895911650739,0.474337166125135],"type":1,"volume":0.018511019721152055},{"fixed":false,"mass":0.02406123613110912,"nu":0,"particle_id":530,"point":[-2.509110965855692,-0.9411375272483931,0.3257914481446679],"type":1,"volume":0.02406123613110912},{"fixed":false,"mass":0.03935627789735215,"nu":0,"particle_id":531,"point":[2.957877943202651,-0.2520975484547896,-0.03625138304485788],"type":1,"volume":0.03935627789735215},{"fixed":false,"mass":0.03853137919536009,"nu":0,"particle_id":532,"point":[3.029849096496132,-0.6056337158711895,0.3054503491134818],"type":1,"volume":0.03853137919536009},{"fixed":false,"mass":0.051108263425029284,"nu":0,"particle_id":533,"point":[2.316881885754631,-0.4996890365316228,-0.3993871482389644],"type":1,"volume":0.051108263425029284},{"fixed":false,"mass":0.04423260978131102,"nu":0,"particle_id":534,"point":[3.536309138901098,0.268974623571743,-0.1640437210979572],"type":1,"volume":0.04423260978131102},{"fixed":false,"mass":0.05023863472054144,"nu":0,"particle_id":535,"point":[3.253080577735389,0.4170510960554207,-0.05687348226694063],"type":1,"volume":0.05023863472054144},{"fixed":false,"mass":0.04717289044059461,"nu":0,"particle_id":536,"point":[-3.741461876280619,0.2456361921027218,0.06529531109390327],"type":1,"volume":0.04717289044059461},{"fixed":false,"mass":0.03608763036135959,"nu":0,"particle_id":537,"point":[-2.821955679438787,0.1766117065736001,-0.240300227855733],"type":1,"volume":0.03608763036135959},{"fixed":false,"mass":0.029514629521622364,"nu":0,"particle_id":538,"point":[-3.082059442334199,-0.6461558805725265,-0.2196586778874818],"type":1,"volume":0.029514629521622364},{"fixed":false,"mass":0.02539223080417045,"nu":0,"particle_id":539,"point":[-2.909948657189764,-0.8366622026525372,-0.5458555797584399],"type":1,"volume":0.02539223080417045},{"fixed":false,"mass":0.020963248016318894,"nu":0,"particle_id":540,"point":[-2.728692660583996,-0.9373156100753249,-0.3383906205754277],"type":1,"volume":0.020963248016318894},{"fixed":false,"mass":0.011248567803923628,"nu":0,"particle_id":541,"point":[-0.6247063411492171,0.6573933262539742,-0.7479055592685269],"type":1,"volume":0.011248567803923628},{"fixed":false,"mass":0.016983032690851198,"nu":0,"particle_id":542,"point":[-0.362224085468793,0.7649400730708279,-0.6366367111291935],"type":1,"volume":0.016983032690851198},{"fixed":false,"mass":0.018641358835003497,"nu":0,"particle_id":543,"point":[-0.4216044254491031,0.4581672381545899,-0.8835325977328519],"type":1,"volume":0.018641358835003497},{"fixed":false,"mass":0.01891793552677203,"nu":0,"particle_id":544,"point":[1.600031023415109,0.01205979252226091,-0.9988122141102864],"type":1,"volume":0.01891793552677203},{"fixed":false,"mass":0.01705899361680456,"nu":0,"particle_id":545,"point":[5,-0.364817421855669,0.9292991275486134],"type":2,"volume":0.01705899361680456},{"fixed":false,"mass":0.015197209352613228,"nu":0,"particle_id":546,"point":[5,0.04728569363338544,0.5906812234423682],"type":2,"volume":0.015197209352613228},{"fixed":false,"mass":0.04292547274804298,"nu":0,"particle_id":547,"point":[-1.64450599246049,-0.1915040440050406,0.1568344259840214],"type":1,"volume":0.04292547274804298},{"fixed":false,"mass":0.029696466736029232,"nu":0,"particle_id":548,"point":[0.2146318326314471,-0.06492480386264761,0.3297917971608947],"type":1,"volume":0.029696466736029232},{"fixed":false,"mass":0.045577608423644264,"nu":0,"particle_id":549,"point":[-4.163345387659064,0.2849947361830114,0.6214436032908858],"type":1,"volume":0.045577608423644264},{"fixed":false,"mass":0.00973900214028752,"nu":0,"particle_id":550,"point":[-4.125782776994046,0.4976742412994103,0.8624156646039027],"type":1,"volume":0.00973900214028752},{"fixed":false,"mass":0.01143922982599067,"nu":0,"particle_id":551,"point":[-3.817925322936671,0.2827707365612491,0.9541877174336512],"type":1,"volume":0.01143922982599067},{"fixed":false,"mass":0.023527874286853767,"nu":0,"particle_id":552,"point":[-3.784167697858088,0.5439094846653414,0.8377024121514174],"type":1,"volume":0.023527874286853767},{"fixed":false,"mass":0.04388231176186716,"nu":0,"particle_id":553,"point":[-1.293606783840107,0.1638433013873401,0.1609843774369132],"type":1,"volume":0.04388231176186716},{"fixed":false,"mass":0.04809917273211399,"nu":0,"particle_id":554,"point":[1.89301306111204,-0.3106255373779593,0.5198801542533201],"type":1,"volume":0.04809917273211399},{"fixed":false,"mass":0.053080351817791714,"nu":0,"particle_id":555,"point":[1.562429606129339,-0.08801092554998488,0.461492401442625],"type":1,"volume":0.053080351817791714},{"fixed":false,"mass":0.05222653556068314,"nu":0,"particle_id":556,"point":[1.545269664882321,-0.4723075794407531,0.4828778815287664],"type":1,"volume":0.05222653556068314},{"fixed":false,"mass":0.07792541214874571,"nu":0,"particle_id":557,"point":[-1.807980591251137,-0.2938145331485476,-0.4090541920152777],"type":1,"volume":0.07792541214874571},{"fixed":false,"mass":0.049364461267894524,"nu":0,"particle_id":558,"point":[-1.600832622137354,-0.0704847186387215,-0.6571433758671843],"type":1,"volume":0.049364461267894524},{"fixed":false,"mass":0.015418068730584539,"nu":0,"particle_id":559,"point":[1.242240150022864,0.6260424749744753,0.7736345379880352],"type":1,"volume":0.015418068730584539},{"fixed":false,"mass":0.016812290352757893,"nu":0,"particle_id":560,"point":[1.480229754070165,0.3946643690660081,0.9174755884255243],"type":1,"volume":0.016812290352757893},{"fixed":false,"mass":0.04493943373492948,"nu":0,"particle_id":561,"point":[1.443335446840895,0.3142590545117552,0.5050711087553296],"type":1,"volume":0.04493943373492948},{"fixed":false,"mass":0.01737019914603044,"nu":0,"particle_id":562,"point":[1.580544482588904,0.7220942787192464,0.688844462603213],"type":1,"volume":0.01737019914603044},{"fixed":false,"mass":0.013622587056140178,"nu":0,"particle_id":563,"point":[0.7913298262029058,-0.7903173653793729,-0.6057143909813545],"type":1,"volume":0.013622587056140178},{"fixed":false,"mass":0.021531480102973774,"nu":0,"particle_id":564,"point":[2.57834076600416,0.2835279679506066,0.9539580138029661],"type":1,"volume":0.021531480102973774},{"fixed":false,"mass":0.01944853763021792,"nu":0,"particle_id":565,"point":[2.60750789168714,0.6021785220832038,0.7932191779912361],"type":1,"volume":0.01944853763021792},{"fixed":false,"mass":0.055164263867054676,"nu":0,"particle_id":566,"point":[-0.813774583816688,0.5951641722279204,0.3558451274044628],"type":1,"volume":0.055164263867054676},{"fixed":false,"mass":0.00968753199860839,"nu":0,"particle_id":567,"point":[-5,0.3522506557514858,-0.2943188194355218],"type":3,"volume":0.00968753199860839},{"fixed":false,"mass":0.010326229312782612,"nu":0,"particle_id":568,"point":[-5,0.5202762034718468,-0.4374703851328893],"type":3,"volume":0.010326229312782612},{"fixed":false,"mass":0.03244027656744117,"nu":0,"particle_id":569,"point":[-4.741226403163841,0.6336329380306298,-0.2859049177918046],"type":1,"volume":0.03244027656744117},{"fixed":false,"mass":0.03933049221446621,"nu":0,"particle_id":570,"point":[-4.721722354569746,0.4487715602269916,-0.5471164750871407],"type":1,"volume":0.03933049221446621},{"fixed":false,"mass":0.04007824558857712,"nu":0,"particle_id":571,"point":[1.373764283709624,0.5989428693773198,0.3661544780066795],"type":1,"volume":0.04007824558857712},{"fixed":false,"mass":0.019426165094731065,"nu":0,"particle_id":572,"point":[1.21082881809085,0.9741127754804431,0.2170866228935245],"type":1,"volume":0.019426165094731065},{"fixed":false,"mass":0.013498784354166772,"nu":0,"particle_id":573,"point":[1.392587566193728,0.9952908266664198,0.04781303924062444],"type":1,"volume":0.013498784354166772},{"fixed":false,"mass":0.03662489592119974,"nu":0,"particle_id":574,"point":[1.420369469837462,0.6856418307328629,-0.1093638098464807],"type":1,"volume":0.03662489592119974},{"fixed":false,"mass":0.012442234754790341,"nu":0,"particle_id":575,"point":[0.598788074679274,-0.1896279578478199,-0.9813232763158151],"type":1,"volume":0.012442234754790341},{"fixed":false,"mass":0.038914751522463785,"nu":0,"particle_id":576,"point":[-4.719830011230203,0.141988227877589,0.6716124340263612],"type":1,"volume":0.038914751522463785},{"fixed":false,"mass":0.00946641076970521,"nu":0,"particle_id":577,"point":[-5,0.02787004600230285,0.9972550400576045],"type":3,"volume":0.00946641076970521},{"fixed":false,"mass":0.01839529007697833,"nu":0,"particle_id":578,"point":[-5,-0.2665543640538293,0.9591069002539181],"type":3,"volume":0.01839529007697833},{"fixed":false,"mass":0.00933855862616374,"nu":0,"particle_id":579,"point":[-4.692820789426184,-0.1206298150342927,0.9881190002305573],"type":1,"volume":0.00933855862616374},{"fixed":false,"mass":0.03653188473408369,"nu":0,"particle_id":580,"point":[1.909011927406466,-0.3500045198417168,-0.5873571514062431],"type":1,"volume":0.03653188473408369},{"fixed":false,"mass":0.013788320625464074,"nu":0,"particle_id":581,"point":[1.730310250498319,-0.6031556878067161,-0.7924172388068247],"type":1,"volume":0.013788320625464074},{"fixed":false,"mass":0.028790620233976844,"nu":0,"particle_id":582,"point":[1.68464738102339,-0.7968862900379108,-0.5977101331256044],"type":1,"volume":0.028790620233976844},{"fixed":false,"mass":0.008736790114574065,"nu":0,"particle_id":583,"point":[5,-0.9509775076979265,-0.2933533798179653],"type":2,"volume":0.008736790114574065},{"fixed":false,"mass":0.034993478079408356,"nu":0,"particle_id":584,"point":[-3.552746958378378,0.2576938651479107,0.6591892465978867],"type":1,"volume":0.034993478079408356},{"fixed":false,"mass":0.026820106738780054,"nu":0,"particle_id":585,"point":[0.3784544155502955,-0.1772691714553776,0.9825405105313982],"type":1,"volume":0.026820106738780054},{"fixed":false,"mass":0.018660745393431013,"nu":0,"particle_id":586,"point":[-1.984110237969525,0.9844260018005973,0.1581254573348489],"type":1,"volume":0.018660745393431013},{"fixed":false,"mass":0.03614642507241911,"nu":0,"particle_id":587,"point":[3.145871085886945,-0.4435259792903743,0.5574328258185868],"type":1,"volume":0.03614642507241911},{"fixed":false,"mass":0.027936926309293675,"nu":0,"particle_id":588,"point":[1.289706773375072,-0.1699523585732498,0.3088320686508029],"type":1,"volume":0.027936926309293675},{"fixed":false,"mass":0.042381339678673656,"nu":0,"particle_id":589,"point":[0.7273845165260759,0.696689893007059,-0.1548439284279397],"type":1,"volume":0.042381339678673656},{"fixed":false,"mass":0.008132582363846803,"nu":0,"particle_id":590,"point":[0.720970660116659,0.9935153603021663,0.06583965175436064],"type":1,"volume":0.008132582363846803},{"fixed":false,"mass":0.020144666246545304,"nu":0,"particle_id":591,"point":[1.021986199230513,0.994518522086614,0.05565437923052247],"type":1,"volume":0.020144666246545304},{"fixed":false,"mass":0.017798734221972673,"nu":0,"particle_id":592,"point":[0.8861194862111342,0.9067777962224608,-0.4146785305746067],"type":1,"volume":0.017798734221972673},{"fixed":false,"mass":0.014743734213202329,"nu":0,"particle_id":593,"point":[-4.596094902149025,-0.9979760723788782,-0.02054928198943803],"type":1,"volume":0.014743734213202329},{"fixed":false,"mass":0.024992877764363094,"nu":0,"particle_id":594,"point":[-4.253779846532244,-0.9827584740724715,-0.1750561504845662],"type":1,"volume":0.024992877764363094},{"fixed":false,"mass":0.041948390211997554,"nu":0,"particle_id":595,"point":[-4.743481358080667,-0.01198972799759832,-0.6844256476961705],"type":1,"volume":0.041948390211997554},{"fixed":false,"mass":0.061780780118433715,"nu":0,"particle_id":596,"point":[-1.535990154594185,0.004887382641169333,-0.1438831633069234],"type":1,"volume":0.061780780118433715},{"fixed":false,"mass":0.01652409290036778,"nu":0,"particle_id":597,"point":[3.121032967955424,0.9262871006803163,0.3747467437538976],"type":1,"volume":0.01652409290036778},{"fixed":false,"mass":0.011282800221159345,"nu":0,"particle_id":598,"point":[-4.488008267321904,-0.01122062559631444,-0.9988948648384737],"type":1,"volume":0.011282800221159345},{"fixed":false,"mass":0.0523840451889808,"nu":0,"particle_id":599,"point":[-1.146021661663344,0.2092623867327648,-0.185623015606248],"type":1,"volume":0.0523840451889808},{"fixed":false,"mass":0.04149801448433661,"nu":0,"particle_id":600,"point":[4.693433058140866,0.08175508041299735,0.2141451693036449],"type":1,"volume":0.04149801448433661},{"fixed":false,"mass":0.03802965408149877,"nu":0,"particle_id":601,"point":[4.375402654026774,0.1394964252882641,0.154512430818948],"type":1,"volume":0.03802965408149877},{"fixed":false,"mass":0.030144360443739308,"nu":0,"particle_id":602,"point":[4.680056220420567,0.2432485237814724,-0.07181705251902776],"type":1,"volume":0.030144360443739308},{"fixed":false,"mass":0.050213124762800244,"nu":0,"particle_id":603,"point":[-4.230134159667958,0.2432398956110736,0.09742579262690607],"type":1,"volume":0.050213124762800244},{"fixed":false,"mass":0.041603213669708594,"nu":0,"particle_id":604,"point":[-3.786384831325708,-0.03161051763199596,0.2770216761074284],"type":1,"volume":0.041603213669708594},{"fixed":false,"mass":0.03637145118619197,"nu":0,"particle_id":605,"point":[-4.422167309558729,0.4103244327179061,-0.1361367443913499],"type":1,"volume":0.03637145118619197},{"fixed":false,"mass":0.06077608621634436,"nu":0,"particle_id":606,"point":[-4.591074029284952,0.5218767776194263,0.2376071322643191],"type":1,"volume":0.06077608621634436},{"fixed":false,"mass":0.010512229984721885,"nu":0,"particle_id":607,"point":[4.163826467824126,-0.1977277342956376,-0.9799852301349365],"type":1,"volume":0.010512229984721885},{"fixed":false,"mass":0.014528269654190766,"nu":0,"particle_id":608,"point":[4.340243541631816,0.07446050698183779,-0.9926662801726729],"type":1,"volume":0.014528269654190766},{"fixed":false,"mass":0.02278554460477448,"nu":0,"particle_id":609,"point":[4.488320570323084,-0.2059490210824351,-0.9774913300531761],"type":1,"volume":0.02278554460477448},{"fixed":false,"mass":0.02453134489198686,"nu":0,"particle_id":610,"point":[-2.507599831019654,-0.3251917085983898,-0.1662079725282857],"type":1,"volume":0.02453134489198686},{"fixed":false,"mass":0.04356856003183317,"nu":0,"particle_id":611,"point":[1.917682403638964,-0.6149249126684821,0.3408176604291094],"type":1,"volume":0.04356856003183317},{"fixed":false,"mass":0.009774985708728777,"nu":0,"particle_id":612,"point":[4.661116578349713,0.4732542658086731,-0.8754684134433468],"type":1,"volume":0.009774985708728777},{"fixed":false,"mass":0.013844227844929212,"nu":0,"particle_id":613,"point":[4.636397599014352,0.07446050698183776,-0.9926662801726729],"type":1,"volume":0.013844227844929212},{"fixed":false,"mass":0.014576045745633745,"nu":0,"particle_id":614,"point":[4.488320570323084,0.3481038288242587,-0.9343691405658545],"type":1,"volume":0.014576045745633745},{"fixed":false,"mass":0.019322392888852596,"nu":0,"particle_id":615,"point":[5,0.2218893377802671,-0.972655887847238],"type":2,"volume":0.019322392888852596},{"fixed":false,"mass":0.041259597506650224,"nu":0,"particle_id":616,"point":[-3.489121441165684,0.2149362391278992,0.325884387759761],"type":1,"volume":0.041259597506650224},{"fixed":false,"mass":0.04026606454124154,"nu":0,"particle_id":617,"point":[-1.138639015034695,-0.2400629374194092,-0.6285981132505296],"type":1,"volume":0.04026606454124154},{"fixed":false,"mass":0.031628791847108526,"nu":0,"particle_id":618,"point":[-0.7274905157977027,-0.2876802307984562,-0.9526984386386049],"type":1,"volume":0.031628791847108526},{"fixed":false,"mass":0.04829496485363478,"nu":0,"particle_id":619,"point":[-4.574654519941896,0.417022827851877,0.5530601972738634],"type":1,"volume":0.04829496485363478},{"fixed":false,"mass":0.02987053915501539,"nu":0,"particle_id":620,"point":[-4.382515799682801,0.1904781888959621,0.4029441553916916],"type":1,"volume":0.02987053915501539},{"fixed":false,"mass":0.044324440661677324,"nu":0,"particle_id":621,"point":[-3.163950808635486,-0.25019501132179,-0.1543223346026414],"type":1,"volume":0.044324440661677324},{"fixed":false,"mass":0.03689241100901186,"nu":0,"particle_id":622,"point":[-2.776663702363368,-0.1516075858922161,-0.2590825155128191],"type":1,"volume":0.03689241100901186},{"fixed":false,"mass":0.041830924309776196,"nu":0,"particle_id":623,"point":[0.7139411366369002,0.4337934095398617,0.4096115645500598],"type":1,"volume":0.041830924309776196},{"fixed":false,"mass":0.04737131124928005,"nu":0,"particle_id":624,"point":[0.4993683482456825,0.09093559815714725,0.4343931700264454],"type":1,"volume":0.04737131124928005},{"fixed":false,"mass":0.02218204117786233,"nu":0,"particle_id":625,"point":[0.7703021905336846,0.4516214175091813,-0.8870314117617619],"type":1,"volume":0.02218204117786233},{"fixed":false,"mass":0.04628013741426055,"nu":0,"particle_id":626,"point":[0.9018249559967544,0.5065005043303028,-0.4118695134071381],"type":1,"volume":0.04628013741426055},{"fixed":false,"mass":0.017886730269221232,"nu":0,"particle_id":627,"point":[-1.535528438334839,-0.9908729100065403,0.0926688998466358],"type":1,"volume":0.017886730269221232},{"fixed":false,"mass":0.053657698569364996,"nu":0,"particle_id":628,"point":[-2.187442448585294,-0.08206022356302697,0.2557157558819413],"type":1,"volume":0.053657698569364996},{"fixed":false,"mass":0.04555928662676743,"nu":0,"particle_id":629,"point":[-2.350424864374347,-0.02787779194807721,0.6775722205212122],"type":1,"volume":0.04555928662676743},{"fixed":false,"mass":0.032870788262845174,"nu":0,"particle_id":630,"point":[-4.327395754995817,0.5542229489225674,-0.4413914844169145],"type":1,"volume":0.032870788262845174},{"fixed":false,"mass":0.04595313913442981,"nu":0,"particle_id":631,"point":[-2.366237732649466,-0.3884288724081464,0.1317294800938162],"type":1,"volume":0.04595313913442981},{"fixed":false,"mass":0.01285187382762814,"nu":0,"particle_id":632,"point":[-3.676576209516508,0.9741655056931362,0.2169127946780121],"type":1,"volume":0.01285187382762814},{"fixed":false,"mass":0.011798851176050111,"nu":0,"particle_id":633,"point":[1.808962312949893,-0.372435126327165,-0.9269883221604844],"type":1,"volume":0.011798851176050111},{"fixed":false,"mass":0.04954398359532222,"nu":0,"particle_id":634,"point":[4.351280776835397,-0.1986246455689966,0.3063166437259053],"type":1,"volume":0.04954398359532222},{"fixed":false,"mass":0.03924772413403381,"nu":0,"particle_id":635,"point":[4.706614010279496,-0.323221534812599,0.2189115852253334],"type":1,"volume":0.03924772413403381},{"fixed":false,"mass":0.012999292833214101,"nu":0,"particle_id":636,"point":[-3.448230227189143,0.7665350668792379,-0.6346932055503549],"type":1,"volume":0.012999292833214101},{"fixed":false,"mass":0.043421267777213224,"nu":0,"particle_id":637,"point":[-3.32690593094136,0.5796975299350845,-0.344776763038902],"type":1,"volume":0.043421267777213224},{"fixed":false,"mass":0.05202202414396951,"nu":0,"particle_id":638,"point":[-1.375319693455053,-0.6754114424022399,0.1304388941651848],"type":1,"volume":0.05202202414396951},{"fixed":false,"mass":0.0192137239779568,"nu":0,"particle_id":639,"point":[-1.104678421744081,-0.8743530487629456,0.4753409663568618],"type":1,"volume":0.0192137239779568},{"fixed":false,"mass":0.024801767545802128,"nu":0,"particle_id":640,"point":[-1.444442000288382,-0.8580233842039799,0.505891619955344],"type":1,"volume":0.024801767545802128},{"fixed":false,"mass":0.03296713600843691,"nu":0,"particle_id":641,"point":[0.2925726381858547,0.7657902314599236,-0.635600790134772],"type":1,"volume":0.03296713600843691},{"fixed":false,"mass":0.03798097929396134,"nu":0,"particle_id":642,"point":[0.009619895223895725,0.6770546748216081,-0.2455305922343799],"type":1,"volume":0.03798097929396134},{"fixed":false,"mass":0.048060389000985256,"nu":0,"particle_id":643,"point":[0.3254521579048236,0.5566800084474709,-0.1797804490234932],"type":1,"volume":0.048060389000985256},{"fixed":false,"mass":0.01371732505911216,"nu":0,"particle_id":644,"point":[0.232379782904118,0.9352122732560246,-0.3453243928332544],"type":1,"volume":0.01371732505911216},{"fixed":false,"mass":0.06188534976812822,"nu":0,"particle_id":645,"point":[1.444535561271253,-0.5841122764054454,-0.242085071064743],"type":1,"volume":0.06188534976812822},{"fixed":false,"mass":0.04646052595929616,"nu":0,"particle_id":646,"point":[-1.271471914264679,0.01761256226764862,-0.4619636548207142],"type":1,"volume":0.04646052595929616},{"fixed":false,"mass":0.049680685651901445,"nu":0,"particle_id":647,"point":[-1.410904295863361,-0.3680358504838481,-0.48264320456259],"type":1,"volume":0.049680685651901445},{"fixed":false,"mass":0.02752102682693328,"nu":0,"particle_id":648,"point":[4.735227128363738,-0.5247402456935325,0.5221319116496578],"type":1,"volume":0.02752102682693328},{"fixed":false,"mass":0.05887868504840855,"nu":0,"particle_id":649,"point":[-3.157381738710829,0.4970662096673659,0.02974889135209569],"type":1,"volume":0.05887868504840855},{"fixed":false,"mass":0.007955771860268884,"nu":0,"particle_id":650,"point":[-5,-0.6998907550833564,-0.7130288207635025],"type":3,"volume":0.007955771860268884},{"fixed":false,"mass":0.014130863156838078,"nu":0,"particle_id":651,"point":[-4.624974620815479,-0.5846438277965926,-0.8076095296959223],"type":1,"volume":0.014130863156838078},{"fixed":false,"mass":0.019855800600684367,"nu":0,"particle_id":652,"point":[4.580847897476351,0.9509856974164264,0.2933263819342146],"type":1,"volume":0.019855800600684367},{"fixed":false,"mass":0.011407730604788186,"nu":0,"particle_id":653,"point":[4.646906927419687,0.8254937487210293,0.5628518438621122],"type":1,"volume":0.011407730604788186},{"fixed":false,"mass":0.041904385326682225,"nu":0,"particle_id":654,"point":[-4.253414912700126,0.6614060015357069,0.06730208274914794],"type":1,"volume":0.041904385326682225},{"fixed":false,"mass":0.04530941301665895,"nu":0,"particle_id":655,"point":[-3.671427197769818,0.518440633269609,0.4723880858931614],"type":1,"volume":0.04530941301665895},{"fixed":false,"mass":0.04494583093656096,"nu":0,"particle_id":656,"point":[-4.048503790611586,-0.5043556453840086,-0.1255254716413129],"type":1,"volume":0.04494583093656096},{"fixed":false,"mass":0.030969101464607983,"nu":0,"particle_id":657,"point":[-3.913677606210549,-0.8817981480559942,-0.4614121652668616],"type":1,"volume":0.030969101464607983},{"fixed":false,"mass":0.03285116441964949,"nu":0,"particle_id":658,"point":[-0.6629633491991008,-0.698062101859113,0.08412102544300182],"type":1,"volume":0.03285116441964949},{"fixed":false,"mass":0.04713138349586757,"nu":0,"particle_id":659,"point":[-0.4570722635997052,-0.387538138885484,-0.1307081317378684],"type":1,"volume":0.04713138349586757},{"fixed":false,"mass":0.024532505378535727,"nu":0,"particle_id":660,"point":[-0.3023490536143678,-0.9762217909957516,-0.2101341304837565],"type":1,"volume":0.024532505378535727},{"fixed":false,"mass":0.01554549554575124,"nu":0,"particle_id":661,"point":[-0.1087242510112853,-0.9982428491656505,0.01784065181788009],"type":1,"volume":0.01554549554575124},{"fixed":false,"mass":0.0192453821388684,"nu":0,"particle_id":662,"point":[-0.4025397659832879,0.2067089095731048,0.97726082039962],"type":1,"volume":0.0192453821388684},{"fixed":false,"mass":0.02607544110295224,"nu":0,"particle_id":663,"point":[-0.7720760308486068,0.1134674706120265,0.9888244295840336],"type":1,"volume":0.02607544110295224},{"fixed":false,"mass":0.009212662006952617,"nu":0,"particle_id":664,"point":[-2.228642004515327,0.01595616123011648,0.9984284552882521],"type":1,"volume":0.009212662006952617},{"fixed":false,"mass":0.02356912010930522,"nu":0,"particle_id":665,"point":[-2.095516302837346,-0.2828061764611767,0.9541769668575406],"type":1,"volume":0.02356912010930522},{"fixed":false,"mass":0.021264512399125017,"nu":0,"particle_id":666,"point":[-1.931132976067855,0.01417055134752818,0.9986043225114375],"type":1,"volume":0.021264512399125017},{"fixed":false,"mass":0.018235558772434782,"nu":0,"particle_id":667,"point":[4.527668614944568,0.6205798941161946,-0.7781175622416132],"type":1,"volume":0.018235558772434782},{"fixed":false,"mass":0.012036327436302247,"nu":0,"particle_id":668,"point":[4.402018392985044,-0.8973570037352268,0.4323035936530157],"type":1,"volume":0.012036327436302247},{"fixed":false,"mass":0.015665080742757517,"nu":0,"particle_id":669,"point":[4.253148278507963,-0.7388009391073256,0.6684873380195371],"type":1,"volume":0.015665080742757517},{"fixed":false,"mass":0.054293539841167845,"nu":0,"particle_id":670,"point":[4.159819484280419,-0.5494065708719695,0.2304299828395665],"type":1,"volume":0.054293539841167845},{"fixed":false,"mass":0.016841808653854918,"nu":0,"particle_id":671,"point":[0.06420236751527389,-0.8166348062959867,-0.5736464964400074],"type":1,"volume":0.016841808653854918},{"fixed":false,"mass":0.022804465229193053,"nu":0,"particle_id":672,"point":[4.135446613322827,0.5313565633892385,-0.8444120883622082],"type":1,"volume":0.022804465229193053},{"fixed":false,"mass":0.038293851415362366,"nu":0,"particle_id":673,"point":[-0.925804355909934,-0.004518178626906955,0.0004785107118250032],"type":1,"volume":0.038293851415362366},{"fixed":false,"mass":0.015283951025091743,"nu":0,"particle_id":674,"point":[-0.8058002516302656,0.4838323941568299,-0.8698142860437397],"type":1,"volume":0.015283951025091743},{"fixed":false,"mass":0.02764721205836933,"nu":0,"particle_id":675,"point":[4.537053949052114,-0.4977671297229341,-0.8623660147071284],"type":1,"volume":0.02764721205836933},{"fixed":false,"mass":0.042666350593617654,"nu":0,"particle_id":676,"point":[4.744240883412082,-0.113931699671622,-0.6524214811341036],"type":1,"volume":0.042666350593617654},{"fixed":false,"mass":0.05777409935713454,"nu":0,"particle_id":677,"point":[-0.8789689135833791,-0.1845625576951531,0.4876599776048535],"type":1,"volume":0.05777409935713454},{"fixed":false,"mass":0.05853359077289568,"nu":0,"particle_id":678,"point":[0.3651332029664986,-0.3601009101974055,0.4105952576288049],"type":1,"volume":0.05853359077289568},{"fixed":false,"mass":0.066511046502814,"nu":0,"particle_id":679,"point":[0.7293715009207702,-0.3144052243746575,0.1151943210496538],"type":1,"volume":0.066511046502814},{"fixed":false,"mass":0.02831411823801933,"nu":0,"particle_id":680,"point":[-0.06956324406863876,0.4828652465812916,0.02756949234738948],"type":1,"volume":0.02831411823801933},{"fixed":false,"mass":0.04547883426501539,"nu":0,"particle_id":681,"point":[-0.08140537661459862,0.2071479515692004,-0.184640419025046],"type":1,"volume":0.04547883426501539},{"fixed":false,"mass":0.053375916224962405,"nu":0,"particle_id":682,"point":[1.721306264450047,0.04066325406646043,0.07333831184449634],"type":1,"volume":0.053375916224962405},{"fixed":false,"mass":0.014287732399183467,"nu":0,"particle_id":683,"point":[-3.655263314690012,-0.9531037493793262,-0.2863441003489614],"type":1,"volume":0.014287732399183467},{"fixed":false,"mass":0.04618251547544299,"nu":0,"particle_id":684,"point":[-3.397621449765101,-0.2695303824920767,-0.6288409866573574],"type":1,"volume":0.04618251547544299},{"fixed":false,"mass":0.0442368433920273,"nu":0,"particle_id":685,"point":[-3.114668595186604,-0.4040995087402937,-0.4625285815680523],"type":1,"volume":0.0442368433920273},{"fixed":false,"mass":0.03206271363914593,"nu":0,"particle_id":686,"point":[-2.964870586279729,-0.2652805292784798,-0.7084884365829499],"type":1,"volume":0.03206271363914593},{"fixed":false,"mass":0.0377434373426539,"nu":0,"particle_id":687,"point":[-2.746029144278229,0.23274152375697,0.1388181166950751],"type":1,"volume":0.0377434373426539},{"fixed":false,"mass":0.05497247418447424,"nu":0,"particle_id":688,"point":[0.9609786967151244,-0.6318375059483623,0.0130832338571793],"type":1,"volume":0.05497247418447424},{"fixed":false,"mass":0.021083472296708903,"nu":0,"particle_id":689,"point":[1.076485150719801,-0.9665677104480226,-0.2419593689631238],"type":1,"volume":0.021083472296708903},{"fixed":false,"mass":0.016716234041704737,"nu":0,"particle_id":690,"point":[-2.625852263264195,0.005913611341259709,-0.9994175601200905],"type":1,"volume":0.016716234041704737},{"fixed":false,"mass":0.01752029411356024,"nu":0,"particle_id":691,"point":[-2.673210761504533,0.4938627594031302,-0.8644529441219393],"type":1,"volume":0.01752029411356024},{"fixed":false,"mass":0.010316047804215992,"nu":0,"particle_id":692,"point":[-2.392813984794203,0.2327979585973867,-0.9693467938996347],"type":1,"volume":0.010316047804215992},{"fixed":false,"mass":0.0445215318847589,"nu":0,"particle_id":693,"point":[3.227536686410194,0.2414455193098374,0.6237660249109391],"type":1,"volume":0.0445215318847589},{"fixed":false,"mass":0.06166101762898608,"nu":0,"particle_id":694,"point":[3.531540547810903,0.3414899535110812,0.3980129684537043],"type":1,"volume":0.06166101762898608},{"fixed":false,"mass":0.042261109507372996,"nu":0,"particle_id":695,"point":[3.791229862212546,0.3032824199607939,0.07845746443107662],"type":1,"volume":0.042261109507372996},{"fixed":false,"mass":0.015116823748407275,"nu":0,"particle_id":696,"point":[3.446416206872865,-0.9941494663090458,0.05940146542270348],"type":1,"volume":0.015116823748407275},{"fixed":false,"mass":0.02835544138151542,"nu":0,"particle_id":697,"point":[1.760624606010169,-0.3179696947472905,0.9435102302014818],"type":1,"volume":0.02835544138151542},{"fixed":false,"mass":0.043966790627099885,"nu":0,"particle_id":698,"point":[1.270265987270252,-0.2528995293844085,0.6205035974268185],"type":1,"volume":0.043966790627099885},{"fixed":false,"mass":0.02006348236481193,"nu":0,"particle_id":699,"point":[1.420489493381388,-0.4826950330226969,0.8704222182355322],"type":1,"volume":0.02006348236481193},{"fixed":false,"mass":0.021660024713002275,"nu":0,"particle_id":700,"point":[1.135671249496635,-0.9920701723240648,0.08051289153814563],"type":1,"volume":0.021660024713002275},{"fixed":false,"mass":0.028203884129266936,"nu":0,"particle_id":701,"point":[1.121201284298835,-0.9115789675157483,0.4056961708624052],"type":1,"volume":0.028203884129266936},{"fixed":false,"mass":0.025905786290736237,"nu":0,"particle_id":702,"point":[-0.7966426182374682,-0.5940829322323882,0.799863056881048],"type":1,"volume":0.025905786290736237},{"fixed":false,"mass":0.06351593929124241,"nu":0,"particle_id":703,"point":[-4.59695996521951,-0.5463100749002197,-0.1563790564372102],"type":1,"volume":0.06351593929124241},{"fixed":false,"mass":0.01761812562007996,"nu":0,"particle_id":704,"point":[-2.358410287233262,-0.9485341105152124,-0.3014081808583398],"type":1,"volume":0.01761812562007996},{"fixed":false,"mass":0.056521634213152545,"nu":0,"particle_id":705,"point":[-2.48178524376985,-0.6519872787805744,-0.1054563664001563],"type":1,"volume":0.056521634213152545},{"fixed":false,"mass":0.016813734565402017,"nu":0,"particle_id":706,"point":[-2.31712962705073,-0.9987034551074612,0.01316404120913029],"type":1,"volume":0.016813734565402017},{"fixed":false,"mass":0.021628118208947875,"nu":0,"particle_id":707,"point":[2.15179084138559,-0.5913269287547391,-0.8021248504826048],"type":1,"volume":0.021628118208947875},{"fixed":false,"mass":0.01345935118941953,"nu":0,"particle_id":708,"point":[1.942478671932009,-0.7342608432310473,-0.6740194608512897],"type":1,"volume":0.01345935118941953},{"fixed":false,"mass":0.008732624868600321,"nu":0,"particle_id":709,"point":[4.651659247048665,0.9999999999999998,1.138195324524555e-15],"type":1,"volume":0.008732624868600321},{"fixed":false,"mass":0.019003588144273477,"nu":0,"particle_id":710,"point":[-4.577237018905443,0.4568524196792358,0.8842353828496827],"type":1,"volume":0.019003588144273477},{"fixed":false,"mass":0.0438809229950362,"nu":0,"particle_id":711,"point":[3.162456851589179,-0.08365666246642264,0.7096093314211761],"type":1,"volume":0.0438809229950362},{"fixed":false,"mass":0.019137069467416213,"nu":0,"particle_id":712,"point":[3.290433060642117,-0.5427722305821285,0.8383102871233004],"type":1,"volume":0.019137069467416213},{"fixed":false,"mass":0.01627944135145098,"nu":0,"particle_id":713,"point":[3.418100172269944,-0.222100176157078,0.9725919307248567],"type":1,"volume":0.01627944135145098},{"fixed":false,"mass":0.03234343830275306,"nu":0,"particle_id":714,"point":[-3.911464790915464,-0.9979760723788782,-0.02054928198943779],"type":1,"volume":0.03234343830275306},{"fixed":false,"mass":0.019601745581188004,"nu":0,"particle_id":715,"point":[0.989604555372442,-0.7426898031901774,0.6637487434240508],"type":1,"volume":0.019601745581188004},{"fixed":false,"mass":0.04434607344161924,"nu":0,"particle_id":716,"point":[-0.1911299317791522,0.4536954592128478,-0.4817539055713745],"type":1,"volume":0.04434607344161924},{"fixed":false,"mass":0.015117173113744161,"nu":0,"particle_id":717,"point":[2.693966039161324,-0.5354653649731094,0.8422158881602178],"type":1,"volume":0.015117173113744161},{"fixed":false,"mass":0.007784944033246456,"nu":0,"particle_id":718,"point":[3.016780682442825,-0.560534530451235,0.8273955186890388],"type":1,"volume":0.007784944033246456},{"fixed":false,"mass":0.039632414107636064,"nu":0,"particle_id":719,"point":[2.893794313750116,-0.244772237738988,0.5711965468415355],"type":1,"volume":0.039632414107636064},{"fixed":false,"mass":0.020653173074459585,"nu":0,"particle_id":720,"point":[3.020624299478619,-0.3126521860584671,0.9451232788272895],"type":1,"volume":0.020653173074459585},{"fixed":false,"mass":0.02623085103993398,"nu":0,"particle_id":721,"point":[1.24071621592031,-0.8582495472868861,-0.5054684985876252],"type":1,"volume":0.02623085103993398},{"fixed":false,"mass":0.04965654399091817,"nu":0,"particle_id":722,"point":[-0.4605098609248872,-0.2184845285796867,-0.5622516634543868],"type":1,"volume":0.04965654399091817},{"fixed":false,"mass":0.009050216071417618,"nu":0,"particle_id":723,"point":[5,-0.8255475727255968,0.5627862591227855],"type":2,"volume":0.009050216071417618},{"fixed":false,"mass":0.01021102014231367,"nu":0,"particle_id":724,"point":[4.663840130288396,-0.8973570037352177,0.4323035936530126],"type":1,"volume":0.01021102014231367},{"fixed":false,"mass":0.008469080771082936,"nu":0,"particle_id":725,"point":[5,-0.9509775076979285,0.2933533798179586],"type":2,"volume":0.008469080771082936},{"fixed":false,"mass":0.02112387187115187,"nu":0,"particle_id":726,"point":[-3.103480325453528,0.710998768010813,-0.7023643815196381],"type":1,"volume":0.02112387187115187},{"fixed":false,"mass":0.03576306965719026,"nu":0,"particle_id":727,"point":[-2.277939546902767,-0.3486618938990526,0.5701262225403555],"type":1,"volume":0.03576306965719026},{"fixed":false,"mass":0.05570313004610678,"nu":0,"particle_id":728,"point":[-2.125932265609058,-0.5666218617516662,0.3293872056422673],"type":1,"volume":0.05570313004610678},{"fixed":false,"mass":0.020095269480922072,"nu":0,"particle_id":729,"point":[-1.824216603629308,0.08209446687597831,-0.9919144007495266],"type":1,"volume":0.020095269480922072},{"fixed":false,"mass":0.025860793346754632,"nu":0,"particle_id":730,"point":[-2.092558955727411,0.2801597126594034,-0.9549797628750955],"type":1,"volume":0.025860793346754632},{"fixed":false,"mass":0.022767332791566976,"nu":0,"particle_id":731,"point":[2.680685232607646,-0.9690587481371093,0.23374751822039],"type":1,"volume":0.022767332791566976},{"fixed":false,"mass":0.0274562182633043,"nu":0,"particle_id":732,"point":[-4.785969590544966,-0.6733459753643487,0.02615977644766874],"type":1,"volume":0.0274562182633043},{"fixed":false,"mass":0.019271165795968687,"nu":0,"particle_id":733,"point":[-4.57501567386343,-0.9298735369712038,-0.3629238477583372],"type":1,"volume":0.019271165795968687},{"fixed":false,"mass":0.03200083954975353,"nu":0,"particle_id":734,"point":[2.852092351235482,0.05627104666597491,0.9944577856454917],"type":1,"volume":0.03200083954975353},{"fixed":false,"mass":0.05912898379063926,"nu":0,"particle_id":735,"point":[-3.259542022845247,-0.5349896367138113,0.02134998157235843],"type":1,"volume":0.05912898379063926},{"fixed":false,"mass":0.0695441455844629,"nu":0,"particle_id":736,"point":[-4.203586046088312,-0.4955663907900864,-0.4515495288910022],"type":1,"volume":0.0695441455844629},{"fixed":false,"mass":0.04279890098558385,"nu":0,"particle_id":737,"point":[-4.256520154963077,-0.2316868155869173,-0.05965435350073278],"type":1,"volume":0.04279890098558385},{"fixed":false,"mass":0.0468369885274939,"nu":0,"particle_id":738,"point":[-3.767660199081937,-0.2666398609965951,-0.05485565286210847],"type":1,"volume":0.0468369885274939},{"fixed":false,"mass":0.02426499030593088,"nu":0,"particle_id":739,"point":[-3.325720822557405,-0.5846438277965949,-0.8076095296959205],"type":1,"volume":0.02426499030593088},{"fixed":false,"mass":0.018130133620084206,"nu":0,"particle_id":740,"point":[0.5733931729742487,0.904147066703071,-0.419600279332395],"type":1,"volume":0.018130133620084206},{"fixed":false,"mass":0.0658237214504222,"nu":0,"particle_id":741,"point":[0.5859797476043693,0.3488194704345844,-0.4410720707104369],"type":1,"volume":0.0658237214504222},{"fixed":false,"mass":0.016577555025124674,"nu":0,"particle_id":742,"point":[0.6658535560512417,0.7388053574815705,-0.6684819542149427],"type":1,"volume":0.016577555025124674},{"fixed":false,"mass":0.023825367635642577,"nu":0,"particle_id":743,"point":[4.556863234858207,-0.4977671297229385,0.8623660147071259],"type":1,"volume":0.023825367635642577},{"fixed":false,"mass":0.006215821098584831,"nu":0,"particle_id":744,"point":[5,-0.6205144679482972,0.7781712561099714],"type":2,"volume":0.006215821098584831},{"fixed":false,"mass":0.01741021535246159,"nu":0,"particle_id":745,"point":[5,0.3705782882363479,-0.4617902932827067],"type":2,"volume":0.01741021535246159},{"fixed":false,"mass":0.026046365278526756,"nu":0,"particle_id":746,"point":[-2.477255275584501,-0.3981460965541221,0.9156145663107814],"type":1,"volume":0.026046365278526756},{"fixed":false,"mass":0.0070767209045681685,"nu":0,"particle_id":747,"point":[0.2590834890717727,-0.7447241479705666,0.6612698871368841],"type":1,"volume":0.0070767209045681685},{"fixed":false,"mass":0.023422642472461883,"nu":0,"particle_id":748,"point":[0.2586867727489252,-0.5671089209906367,0.8220000558107274],"type":1,"volume":0.023422642472461883},{"fixed":false,"mass":0.011632210988823414,"nu":0,"particle_id":749,"point":[0.4932288421172942,-0.712641988240192,0.700362111876822],"type":1,"volume":0.011632210988823414},{"fixed":false,"mass":0.00974767425074466,"nu":0,"particle_id":750,"point":[-5,0.3201523955821015,0.9428481151419349],"type":3,"volume":0.00974767425074466},{"fixed":false,"mass":0.019726543663402357,"nu":0,"particle_id":751,"point":[-0.1877877425951968,-0.9361801382995315,0.3421337693789372],"type":1,"volume":0.019726543663402357},{"fixed":false,"mass":0.016194855397168403,"nu":0,"particle_id":752,"point":[-5,-0.02194905635951594,0.009491427548765974],"type":3,"volume":0.016194855397168403},{"fixed":false,"mass":0.019301457989369216,"nu":0,"particle_id":753,"point":[-5,0.2607148816636544,-0.02470847594036885],"type":3,"volume":0.019301457989369216},{"fixed":false,"mass":0.04599286913949686,"nu":0,"particle_id":754,"point":[3.9830492563974,0.1170449999288404,-0.2431364624687885],"type":1,"volume":0.04599286913949686},{"fixed":false,"mass":0.035103590600866846,"nu":0,"particle_id":755,"point":[-2.640703135364204,-0.09812191513921689,-0.6658512296991435],"type":1,"volume":0.035103590600866846},{"fixed":false,"mass":0.039917069243399654,"nu":0,"particle_id":756,"point":[0.5915303231559501,-0.6564890990073797,0.05885906579729908],"type":1,"volume":0.039917069243399654},{"fixed":false,"mass":0.05010788483142471,"nu":0,"particle_id":757,"point":[1.086737415971635,0.5860076402739114,-0.1203900270826509],"type":1,"volume":0.05010788483142471},{"fixed":false,"mass":0.014587918212517984,"nu":0,"particle_id":758,"point":[-1.214605500099896,0.2330549143663812,-0.9692688472192765],"type":1,"volume":0.014587918212517984},{"fixed":false,"mass":0.0207753339547525,"nu":0,"particle_id":759,"point":[-1.489595967843478,0.1070864285505619,-0.9894529073715486],"type":1,"volume":0.0207753339547525},{"fixed":false,"mass":0.03870175008191548,"nu":0,"particle_id":760,"point":[2.324497522541967,0.02329915440803595,-0.7128572065011474],"type":1,"volume":0.03870175008191548},{"fixed":false,"mass":0.029551568087968015,"nu":0,"particle_id":761,"point":[1.075248433600345,-0.2407625866530808,0.966930750392774],"type":1,"volume":0.029551568087968015},{"fixed":false,"mass":0.020705479512787128,"nu":0,"particle_id":762,"point":[3.513410472270683,0.3414646164806373,0.936383123612057],"type":1,"volume":0.020705479512787128},{"fixed":false,"mass":0.016280086777034623,"nu":0,"particle_id":763,"point":[3.492990668630723,0.6114945156414721,0.7855737396624688],"type":1,"volume":0.016280086777034623},{"fixed":false,"mass":0.03623205762978816,"nu":0,"particle_id":764,"point":[-4.003302870551722,0.0007608749557562189,0.00204800320250929],"type":1,"volume":0.03623205762978816},{"fixed":false,"mass":0.04701038759279535,"nu":0,"particle_id":765,"point":[-4.055683451346948,-0.188774891869352,0.4815650360858951],"type":1,"volume":0.04701038759279535},{"fixed":false,"mass":0.03830909498355915,"nu":0,"particle_id":766,"point":[-4.244694915732348,-0.06473154205031231,0.2322943648967957],"type":1,"volume":0.03830909498355915},{"fixed":false,"mass":0.06385659070157333,"nu":0,"particle_id":767,"point":[-4.091361842785781,-0.5393319919165178,0.2777603225657664],"type":1,"volume":0.06385659070157333},{"fixed":false,"mass":0.024173489463410677,"nu":0,"particle_id":768,"point":[2.220043793660867,-0.3763646622642715,0.9257963104658471],"type":1,"volume":0.024173489463410677},{"fixed":false,"mass":0.0490968068717543,"nu":0,"particle_id":769,"point":[2.544774362300753,-0.2776724166634312,0.6556272919154937],"type":1,"volume":0.0490968068717543},{"fixed":false,"mass":0.012697781256393838,"nu":0,"particle_id":770,"point":[-5,0.4073815467443078,-0.9106781153386083],"type":3,"volume":0.012697781256393838},{"fixed":false,"mass":0.052585490146261835,"nu":0,"particle_id":771,"point":[3.502109060749879,0.5711175641972807,-0.3095446411600226],"type":1,"volume":0.052585490146261835},{"fixed":false,"mass":0.016735142609989984,"nu":0,"particle_id":772,"point":[3.226494421798939,0.1024221451079542,0.9899122991934665],"type":1,"volume":0.016735142609989984},{"fixed":false,"mass":0.01390415732930089,"nu":0,"particle_id":773,"point":[1.453857954698241,-0.5774988543781401,-0.813473257841481],"type":1,"volume":0.01390415732930089},{"fixed":false,"mass":0.01530294321183761,"nu":0,"particle_id":774,"point":[0.256209010899544,0.5009621701354976,0.8606582300268001],"type":1,"volume":0.01530294321183761},{"fixed":false,"mass":0.01855084268985284,"nu":0,"particle_id":775,"point":[-4.075596602671359,0.7229906538958051,0.6877522262903268],"type":1,"volume":0.01855084268985284},{"fixed":false,"mass":0.03179839848979382,"nu":0,"particle_id":776,"point":[-4.281928690919859,0.53073895025119,0.4117426766153431],"type":1,"volume":0.03179839848979382},{"fixed":false,"mass":0.01595260610920712,"nu":0,"particle_id":777,"point":[-4.188308908225315,0.877110250902642,0.4701826039687858],"type":1,"volume":0.01595260610920712},{"fixed":false,"mass":0.013113198798782949,"nu":0,"particle_id":778,"point":[-4.555990556609528,-0.6564419374057988,0.7486863439180553],"type":1,"volume":0.013113198798782949},{"fixed":false,"mass":0.04192611840109016,"nu":0,"particle_id":779,"point":[-4.334146975282854,-0.4104455021813264,0.5446612585311107],"type":1,"volume":0.04192611840109016},{"fixed":false,"mass":0.02521401235283282,"nu":0,"particle_id":780,"point":[-4.165267002179339,-0.6564419374057989,0.7486863439180553],"type":1,"volume":0.02521401235283282},{"fixed":false,"mass":0.009538295062898657,"nu":0,"particle_id":781,"point":[4.628626286996941,-0.7309668637931759,0.6780331864095501],"type":1,"volume":0.009538295062898657},{"fixed":false,"mass":0.009917756762908521,"nu":0,"particle_id":782,"point":[4.596282613920263,-0.9828092080243529,0.1745410400266877],"type":1,"volume":0.009917756762908521},{"fixed":false,"mass":0.03169655195659053,"nu":0,"particle_id":783,"point":[4.575169188762191,-0.9828092080243529,-0.1745410400266891],"type":1,"volume":0.03169655195659053},{"fixed":false,"mass":0.02904667974913953,"nu":0,"particle_id":784,"point":[-4.12318954898115,-0.319963410395838,-0.942905443171439],"type":1,"volume":0.02904667974913953},{"fixed":false,"mass":0.016080490818060518,"nu":0,"particle_id":785,"point":[-3.862629353307292,0.02778959530283349,-0.9972629637598964],"type":1,"volume":0.016080490818060518},{"fixed":false,"mass":0.03565907143878796,"nu":0,"particle_id":786,"point":[-3.697629259143497,-0.1814585211842585,-0.70247282031566],"type":1,"volume":0.03565907143878796},{"fixed":false,"mass":0.0449862962422117,"nu":0,"particle_id":787,"point":[3.655620038152969,-0.4760945690381373,0.484409348778537],"type":1,"volume":0.0449862962422117},{"fixed":false,"mass":0.017612863195744247,"nu":0,"particle_id":788,"point":[-4.121247670649532,-0.6159340426210336,-0.781930314029031],"type":1,"volume":0.017612863195744247},{"fixed":false,"mass":0.018003852265482307,"nu":0,"particle_id":789,"point":[-3.78529660158711,-0.5961918727628399,-0.7981322941165876],"type":1,"volume":0.018003852265482307},{"fixed":false,"mass":0.020299400312818655,"nu":0,"particle_id":790,"point":[-1.92856581210051,-0.6848282193745908,-0.7253903243557858],"type":1,"volume":0.020299400312818655},{"fixed":false,"mass":0.038496112712237,"nu":0,"particle_id":791,"point":[-3.491983949902207,-0.2518959286380135,-0.2873505353339552],"type":1,"volume":0.038496112712237},{"fixed":false,"mass":0.019302703553633952,"nu":0,"particle_id":792,"point":[5,0.2948672572053729,0.3659930539337671],"type":2,"volume":0.019302703553633952},{"fixed":false,"mass":0.011497013718417822,"nu":0,"particle_id":793,"point":[-1.817909920598321,0.4000230401755194,-0.9146113190435923],"type":1,"volume":0.011497013718417822},{"fixed":false,"mass":0.013675916571746854,"nu":0,"particle_id":794,"point":[-4.58084524739289,0.9899379122074039,-0.1021620918133077],"type":1,"volume":0.013675916571746854},{"fixed":false,"mass":0.037413255796241836,"nu":0,"particle_id":795,"point":[-4.697874729556153,0.7229412841159919,0.01893974149319015],"type":1,"volume":0.037413255796241836},{"fixed":false,"mass":0.020332608497828274,"nu":0,"particle_id":796,"point":[-4.374136593308616,0.9807852804032298,0.1950903220161303],"type":1,"volume":0.020332608497828274},{"fixed":false,"mass":0.01952678434740736,"nu":0,"particle_id":797,"point":[2.738697447309816,-0.7337335150551711,-0.6746620120927369],"type":1,"volume":0.01952678434740736},{"fixed":false,"mass":0.015127647529468186,"nu":0,"particle_id":798,"point":[3.034958788831322,-0.8108888957501768,-0.58064790869779],"type":1,"volume":0.015127647529468186},{"fixed":false,"mass":0.01562086361559946,"nu":0,"particle_id":799,"point":[2.892983558139663,-0.5162743990345224,-0.8524736731640439],"type":1,"volume":0.01562086361559946},{"fixed":false,"mass":0.03050647423898588,"nu":0,"particle_id":800,"point":[2.866927321559395,-0.6094732371651493,-0.3853964917095188],"type":1,"volume":0.03050647423898588},{"fixed":false,"mass":0.013090310443179997,"nu":0,"particle_id":801,"point":[-5,-0.9194790601203947,0.3909161371581612],"type":3,"volume":0.013090310443179997},{"fixed":false,"mass":0.02631116772221521,"nu":0,"particle_id":802,"point":[-1.558907941159893,0.5308945188922446,0.8446590562911562],"type":1,"volume":0.02631116772221521},{"fixed":false,"mass":0.013993073534030271,"nu":0,"particle_id":803,"point":[1.969620072172437,0.01500244206780216,-0.9985223884269576],"type":1,"volume":0.013993073534030271},{"fixed":false,"mass":0.0201474987358745,"nu":0,"particle_id":804,"point":[3.946617208917687,-0.7993972913085472,0.5946504692245781],"type":1,"volume":0.0201474987358745},{"fixed":false,"mass":0.020094895248627398,"nu":0,"particle_id":805,"point":[-3.894467368939464,0.9984241346247207,-0.01600002966314398],"type":1,"volume":0.020094895248627398},{"fixed":false,"mass":0.03922739405685095,"nu":0,"particle_id":806,"point":[-1.435341336616564,-0.01284393111281267,0.4082116907052072],"type":1,"volume":0.03922739405685095},{"fixed":false,"mass":0.012290381395306865,"nu":0,"particle_id":807,"point":[0.643900004609198,-0.8668404512045444,0.4893960478193609],"type":1,"volume":0.012290381395306865},{"fixed":false,"mass":0.014514420894431786,"nu":0,"particle_id":808,"point":[-3.559412831844858,0.990543017157963,-0.09601835814789468],"type":1,"volume":0.014514420894431786},{"fixed":false,"mass":0.021275019131801767,"nu":0,"particle_id":809,"point":[2.898449202692757,0.09205556262774353,-0.9909333184499602],"type":1,"volume":0.021275019131801767},{"fixed":false,"mass":0.03346719578763471,"nu":0,"particle_id":810,"point":[4.22662738303064,-0.3191689821825426,-0.5974749040944758],"type":1,"volume":0.03346719578763471},{"fixed":false,"mass":0.01662373190053668,"nu":0,"particle_id":811,"point":[-5,0.9374285201046061,0.3380184060915296],"type":3,"volume":0.01662373190053668},{"fixed":false,"mass":0.013011762229091658,"nu":0,"particle_id":812,"point":[-5,0.7959373748408309,0.5988663896387303],"type":3,"volume":0.013011762229091658},{"fixed":false,"mass":0.019345526770172202,"nu":0,"particle_id":813,"point":[-4.58084524739289,0.8754876355926597,0.4732183036967173],"type":1,"volume":0.019345526770172202},{"fixed":false,"mass":0.014815123966495005,"nu":0,"particle_id":814,"point":[-2.03281933427589,-0.8362293125187303,0.5466654602355543],"type":1,"volume":0.014815123966495005},{"fixed":false,"mass":0.036947354115734604,"nu":0,"particle_id":815,"point":[4.175407123636684,-0.6582773800494885,-0.08516772705858519],"type":1,"volume":0.036947354115734604},{"fixed":false,"mass":0.007446383099660169,"nu":0,"particle_id":816,"point":[4.199225869966604,-0.9916395398294391,-0.0848851766305172],"type":1,"volume":0.007446383099660169},{"fixed":false,"mass":0.013185652121470054,"nu":0,"particle_id":817,"point":[4.34015412990535,-0.8973570037352149,-0.4323035936530183],"type":1,"volume":0.013185652121470054},{"fixed":false,"mass":0.01491166149165613,"nu":0,"particle_id":818,"point":[-2.904128987013562,0.06165625224470335,-0.9939273891906759],"type":1,"volume":0.01491166149165613},{"fixed":false,"mass":0.013955282277620622,"nu":0,"particle_id":819,"point":[2.497323416623495,0.5361354073337034,-0.8418577430569207],"type":1,"volume":0.013955282277620622},{"fixed":false,"mass":0.04898774337717699,"nu":0,"particle_id":820,"point":[-1.76505612723359,0.3697171384924154,0.3796066055044007],"type":1,"volume":0.04898774337717699},{"fixed":false,"mass":0.04454944396515345,"nu":0,"particle_id":821,"point":[-0.5644856060732086,-0.4583832890792475,0.3056824200135005],"type":1,"volume":0.04454944396515345},{"fixed":false,"mass":0.018722881220347157,"nu":0,"particle_id":822,"point":[-5,-0.4686214856700356,-0.3595028107137161],"type":3,"volume":0.018722881220347157},{"fixed":false,"mass":0.013998868752778433,"nu":0,"particle_id":823,"point":[-5,-0.9807852804032304,-0.1950903220161282],"type":3,"volume":0.013998868752778433},{"fixed":false,"mass":0.01721389347247809,"nu":0,"particle_id":824,"point":[3.03725880926227,-0.9511585932163743,-0.2927564208656069],"type":1,"volume":0.01721389347247809},{"fixed":false,"mass":0.022467796987973035,"nu":0,"particle_id":825,"point":[3.882918686749066,-0.2799989074428845,-0.9550285426042333],"type":1,"volume":0.022467796987973035},{"fixed":false,"mass":0.010263179752784981,"nu":0,"particle_id":826,"point":[3.607092490457497,0.03846000412448825,0.9962120202206568],"type":1,"volume":0.010263179752784981},{"fixed":false,"mass":0.007406331910879846,"nu":0,"particle_id":827,"point":[3.854120641958811,0.1938815714248295,0.9809043319452762],"type":1,"volume":0.007406331910879846},{"fixed":false,"mass":0.05902785065158163,"nu":0,"particle_id":828,"point":[3.819205945894908,0.1931039288906354,0.6006340772910255],"type":1,"volume":0.05902785065158163},{"fixed":false,"mass":0.01725582004785352,"nu":0,"particle_id":829,"point":[-2.638278484060216,0.5270761876683603,0.8466999968510709],"type":1,"volume":0.01725582004785352},{"fixed":false,"mass":0.005248405779357761,"nu":0,"particle_id":830,"point":[-4.700376131771309,0.5389652345127411,-0.8403451689169088],"type":1,"volume":0.005248405779357761},{"fixed":false,"mass":0.016812048295838693,"nu":0,"particle_id":831,"point":[2.501885029966194,-0.5263717930434294,-0.8470765036222003],"type":1,"volume":0.016812048295838693},{"fixed":false,"mass":0.04286497673874116,"nu":0,"particle_id":832,"point":[4.065597221477949,0.3112195992560938,0.2801213078028672],"type":1,"volume":0.04286497673874116},{"fixed":false,"mass":0.02837434048394912,"nu":0,"particle_id":833,"point":[1.017141173423075,0.1305377899294842,-0.9871431498787024],"type":1,"volume":0.02837434048394912},{"fixed":false,"mass":0.0158565095773368,"nu":0,"particle_id":834,"point":[5,0.2712872660223193,0.08321216776031559],"type":2,"volume":0.0158565095773368},{"fixed":false,"mass":0.009419481611833955,"nu":0,"particle_id":835,"point":[-4.651655689130825,0.9807852804032298,0.1950903220161303],"type":1,"volume":0.009419481611833955},{"fixed":false,"mass":0.018443206010338373,"nu":0,"particle_id":836,"point":[-0.8031032684701176,-0.9707535534354219,0.2281604939016847],"type":1,"volume":0.018443206010338373},{"fixed":false,"mass":0.02027613119084177,"nu":0,"particle_id":837,"point":[1.262267296448422,0.9580817586416335,-0.2699338030511317],"type":1,"volume":0.02027613119084177},{"fixed":false,"mass":0.028141821775393157,"nu":0,"particle_id":838,"point":[1.293651981452946,0.7310782402631218,-0.6778974737882539],"type":1,"volume":0.028141821775393157},{"fixed":false,"mass":0.0075897394738910955,"nu":0,"particle_id":839,"point":[1.36974854875998,0.5388161648680234,-0.8404248483020427],"type":1,"volume":0.0075897394738910955},{"fixed":false,"mass":0.021374422102044578,"nu":0,"particle_id":840,"point":[4.189074664752528,0.9519411477932254,0.2901766841513459],"type":1,"volume":0.021374422102044578},{"fixed":false,"mass":0.013233285206053871,"nu":0,"particle_id":841,"point":[4.07668894826651,0.8434329335823109,0.5331884331372012],"type":1,"volume":0.013233285206053871},{"fixed":false,"mass":0.012902547585083001,"nu":0,"particle_id":842,"point":[5,-0.4833066695067952,0.4422761036295141],"type":2,"volume":0.012902547585083001},{"fixed":false,"mass":0.012343483213434625,"nu":0,"particle_id":843,"point":[0.727062545857337,-0.207079546841794,0.9771483888133419],"type":1,"volume":0.012343483213434625},{"fixed":false,"mass":0.015482192467032757,"nu":0,"particle_id":844,"point":[0.9957649693179921,-0.5099445397569482,0.8558570534369088],"type":1,"volume":0.015482192467032757},{"fixed":false,"mass":0.01959246860361251,"nu":0,"particle_id":845,"point":[-0.8975422127263668,-0.6608012458279237,-0.7451087519533367],"type":1,"volume":0.01959246860361251},{"fixed":false,"mass":0.013538372376151577,"nu":0,"particle_id":846,"point":[-1.590397062036574,-0.01883960355718587,0.9981444610069601],"type":1,"volume":0.013538372376151577},{"fixed":false,"mass":0.020767270134644945,"nu":0,"particle_id":847,"point":[3.32939208073347,-0.7309668637931708,-0.678033186409555],"type":1,"volume":0.020767270134644945},{"fixed":false,"mass":0.011191740042498243,"nu":0,"particle_id":848,"point":[3.452301998944413,-0.5254232857043446,-0.8475834913574724],"type":1,"volume":0.011191740042498243},{"fixed":false,"mass":0.045414556623350186,"nu":0,"particle_id":849,"point":[-1.081096756120432,0.3551715364913108,0.3360883481964242],"type":1,"volume":0.045414556623350186},{"fixed":false,"mass":0.017293193276352727,"nu":0,"particle_id":850,"point":[-0.5812257352390371,-0.2163072499423103,0.9743491956804871],"type":1,"volume":0.017293193276352727},{"fixed":false,"mass":0.037603696194073014,"nu":0,"particle_id":851,"point":[2.644548139484103,-0.3927657155120101,-0.2828718274028114],"type":1,"volume":0.037603696194073014},{"fixed":false,"mass":0.03978744088441872,"nu":0,"particle_id":852,"point":[2.658521506043542,-0.07621423898765414,-0.2234505574181146],"type":1,"volume":0.03978744088441872},{"fixed":false,"mass":0.0106268982577767,"nu":0,"particle_id":853,"point":[5,0.02646898453246005,0.3189956443125266],"type":2,"volume":0.0106268982577767},{"fixed":false,"mass":0.013713353459169362,"nu":0,"particle_id":854,"point":[3.773238805576417,0.3646659590504729,-0.9293450732882595],"type":1,"volume":0.013713353459169362},{"fixed":false,"mass":0.02360820135163886,"nu":0,"particle_id":855,"point":[0.9950934131828526,0.8563774796715395,0.5089708907539108],"type":1,"volume":0.02360820135163886},{"fixed":false,"mass":0.019486648044457735,"nu":0,"particle_id":856,"point":[0.88411807014029,0.5865227873318022,0.8060675074565504],"type":1,"volume":0.019486648044457735},{"fixed":false,"mass":0.012763282508467994,"nu":0,"particle_id":857,"point":[3.818366933684946,0.4623361672706512,0.8813042586953279],"type":1,"volume":0.012763282508467994},{"fixed":false,"mass":0.018931987093101885,"nu":0,"particle_id":858,"point":[-0.6460126253697802,0.8343841664851861,-0.550117485664851],"type":1,"volume":0.018931987093101885},{"fixed":false,"mass":0.018161190684423505,"nu":0,"particle_id":859,"point":[2.110380356184603,-0.8973570037352183,0.4323035936530122],"type":1,"volume":0.018161190684423505},{"fixed":false,"mass":0.05010517658841071,"nu":0,"particle_id":860,"point":[2.360893113207643,-0.5947028171352703,0.3999710556624263],"type":1,"volume":0.05010517658841071},{"fixed":false,"mass":0.023264814532171496,"nu":0,"particle_id":861,"point":[1.383589199207631,-0.8064454846182815,0.5860622208276414],"type":1,"volume":0.023264814532171496},{"fixed":false,"mass":0.014497213141698743,"nu":0,"particle_id":862,"point":[3.479599049134957,0.5705701506351553,-0.8191594980512836],"type":1,"volume":0.014497213141698743},{"fixed":false,"mass":0.012408852546405853,"nu":0,"particle_id":863,"point":[1.769285988296441,0.5161767369817982,0.8525258746187849],"type":1,"volume":0.012408852546405853},{"fixed":false,"mass":0.034592000627915474,"nu":0,"particle_id":864,"point":[1.771608700474546,0.481752322847868,0.4839176413632587],"type":1,"volume":0.034592000627915474},{"fixed":false,"mass":0.010651721681210891,"nu":0,"particle_id":865,"point":[-5,0.4885003967766002,0.4371610526780115],"type":3,"volume":0.010651721681210891},{"fixed":false,"mass":0.014833194805495735,"nu":0,"particle_id":866,"point":[-5,-0.3864359186248838,0.4470709954313534],"type":3,"volume":0.014833194805495735},{"fixed":false,"mass":0.01794567472906878,"nu":0,"particle_id":867,"point":[-5,-0.4773034020708162,-0.004523725118074558],"type":3,"volume":0.01794567472906878},{"fixed":false,"mass":0.04308640164938407,"nu":0,"particle_id":868,"point":[-1.426405862694348,-0.3878560180986912,-0.07281324780605901],"type":1,"volume":0.04308640164938407},{"fixed":false,"mass":0.026378546662816364,"nu":0,"particle_id":869,"point":[-2.731274653831263,0.8576608919516374,-0.5065697952597732],"type":1,"volume":0.026378546662816364},{"fixed":false,"mass":0.0070741496201421825,"nu":0,"particle_id":870,"point":[-5,-0.9899351468778825,0.1021901686751149],"type":3,"volume":0.0070741496201421825},{"fixed":false,"mass":0.018581905706613777,"nu":0,"particle_id":871,"point":[0.4713995813249322,0.9875081498519696,0.1268318830094318],"type":1,"volume":0.018581905706613777},{"fixed":false,"mass":0.06623392550933589,"nu":0,"particle_id":872,"point":[3.847102991334348,-0.1636705955856283,0.467371926458766],"type":1,"volume":0.06623392550933589},{"fixed":false,"mass":0.019588253947273235,"nu":0,"particle_id":873,"point":[0.7896638888172067,-0.9172572018855103,-0.3950729415452727],"type":1,"volume":0.019588253947273235},{"fixed":false,"mass":0.038908773110140474,"nu":0,"particle_id":874,"point":[-1.226829747770519,-0.1642705062822924,0.1433615889100902],"type":1,"volume":0.038908773110140474},{"fixed":false,"mass":0.03526648662081646,"nu":0,"particle_id":875,"point":[-4.720064496188005,-0.434945482037616,0.5697399135833435],"type":1,"volume":0.03526648662081646},{"fixed":false,"mass":0.012680080554107648,"nu":0,"particle_id":876,"point":[2.755808775921264,-0.9953549805220134,-0.04716167421376027],"type":1,"volume":0.012680080554107648},{"fixed":false,"mass":0.0072027454020024955,"nu":0,"particle_id":877,"point":[3.023494341624243,-0.9971668136219628,-0.02876582403606389],"type":1,"volume":0.0072027454020024955},{"fixed":false,"mass":0.014012705417763107,"nu":0,"particle_id":878,"point":[3.782929527686883,0.6962160491436713,0.7160445739907342],"type":1,"volume":0.014012705417763107},{"fixed":false,"mass":0.020516304172907767,"nu":0,"particle_id":879,"point":[-1.891106079300321,0.5453452477067415,0.836934980817202],"type":1,"volume":0.020516304172907767},{"fixed":false,"mass":0.041408742325363596,"nu":0,"particle_id":880,"point":[3.048088433835933,-0.05568346955649797,-0.3292773400576424],"type":1,"volume":0.041408742325363596},{"fixed":false,"mass":0.021391988707228065,"nu":0,"particle_id":881,"point":[0.008336871805605078,-0.6601232310681446,0.7456651842865538],"type":1,"volume":0.021391988707228065},{"fixed":false,"mass":0.014983601470775588,"nu":0,"particle_id":882,"point":[0.07599930308057459,-0.84278937191939,0.5343924523233983],"type":1,"volume":0.014983601470775588},{"fixed":false,"mass":0.02189420570375484,"nu":0,"particle_id":883,"point":[-1.372123272411018,-0.2496166080841051,-0.9642449123550845],"type":1,"volume":0.02189420570375484},{"fixed":false,"mass":0.019904632212475827,"nu":0,"particle_id":884,"point":[-1.032981313808654,-0.8420790047835215,-0.535721455758668],"type":1,"volume":0.019904632212475827},{"fixed":false,"mass":0.015815439853529747,"nu":0,"particle_id":885,"point":[-0.6021665887164753,-0.8744059767559906,-0.4752419450465744],"type":1,"volume":0.015815439853529747},{"fixed":false,"mass":0.01029179829843091,"nu":0,"particle_id":886,"point":[1.735460826894034,-0.8341046198297002,0.5506404806722207],"type":1,"volume":0.01029179829843091},{"fixed":false,"mass":0.0209262717349097,"nu":0,"particle_id":887,"point":[1.538350053799626,-0.9026780584977,0.4223486003804833],"type":1,"volume":0.0209262717349097},{"fixed":false,"mass":0.012516437978313918,"nu":0,"particle_id":888,"point":[2.478435503219927,0.9523860387624878,0.2887100751745417],"type":1,"volume":0.012516437978313918},{"fixed":false,"mass":0.021088704992721963,"nu":0,"particle_id":889,"point":[-3.30455601618833,0.9934259716528349,-0.0667472299417394],"type":1,"volume":0.021088704992721963},{"fixed":false,"mass":0.0172079693389394,"nu":0,"particle_id":890,"point":[-2.378431927216949,-0.7173683464688816,0.6946030277119722],"type":1,"volume":0.0172079693389394},{"fixed":false,"mass":0.016660192492417705,"nu":0,"particle_id":891,"point":[-0.4857359066954128,-0.9974165633826857,0.02623007216118839],"type":1,"volume":0.016660192492417705},{"fixed":false,"mass":0.014560748411540234,"nu":0,"particle_id":892,"point":[-2.097623578467058,0.3086850244080812,0.9463267041572685],"type":1,"volume":0.014560748411540234},{"fixed":false,"mass":0.01267607996295548,"nu":0,"particle_id":893,"point":[-3.214744532648337,-0.8398856871694207,-0.5398248643998951],"type":1,"volume":0.01267607996295548},{"fixed":false,"mass":0.022377622970051744,"nu":0,"particle_id":894,"point":[-1.812830046359739,-0.2520681666026048,-0.9635012402088283],"type":1,"volume":0.022377622970051744},{"fixed":false,"mass":0.01909228000998195,"nu":0,"particle_id":895,"point":[3.589271282503012,-0.2881055890537506,-0.9525694076225162],"type":1,"volume":0.01909228000998195},{"fixed":false,"mass":0.06093045971196903,"nu":0,"particle_id":896,"point":[3.373690414531628,-0.1764079259111183,-0.591523158755267],"type":1,"volume":0.06093045971196903},{"fixed":false,"mass":0.023449475561800208,"nu":0,"particle_id":897,"point":[-3.519368227026429,-0.8340798301519676,-0.5506868588972289],"type":1,"volume":0.023449475561800208},{"fixed":false,"mass":0.017805617195813455,"nu":0,"particle_id":898,"point":[3.537881526398872,0.8038592670669084,0.589213536031927],"type":1,"volume":0.017805617195813455},{"fixed":false,"mass":0.018987091955239108,"nu":0,"particle_id":899,"point":[-1.163341097459726,-0.5375675683470245,-0.841092237046826],"type":1,"volume":0.018987091955239108},{"fixed":false,"mass":0.009353736786114375,"nu":0,"particle_id":900,"point":[-3.841488815425527,-0.3528605276076728,-0.932926211764987],"type":1,"volume":0.009353736786114375},{"fixed":false,"mass":0.008954560169800868,"nu":0,"particle_id":901,"point":[-3.562544816325609,-0.401470932539006,-0.9138374044516511],"type":1,"volume":0.008954560169800868},{"fixed":false,"mass":0.007114702339142866,"nu":0,"particle_id":902,"point":[-5,-0.5391048234334587,0.8402705570843298],"type":3,"volume":0.007114702339142866},{"fixed":false,"mass":0.015302148062196867,"nu":0,"particle_id":903,"point":[-4.628747665391915,-0.407575856505218,0.9105742546075779],"type":1,"volume":0.015302148062196867},{"fixed":false,"mass":0.017590454156708343,"nu":0,"particle_id":904,"point":[-0.3776344181208402,-0.069295128800567,-0.9931750255186167],"type":1,"volume":0.017590454156708343},{"fixed":false,"mass":0.03826396308753533,"nu":0,"particle_id":905,"point":[-1.957662369118821,0.4999752936494293,-0.477768005489685],"type":1,"volume":0.03826396308753533},{"fixed":false,"mass":0.01938390312650966,"nu":0,"particle_id":906,"point":[-2.329940771192556,0.5083998349155636,-0.8566827153763861],"type":1,"volume":0.01938390312650966},{"fixed":false,"mass":0.014400340208420098,"nu":0,"particle_id":907,"point":[-2.313483057881715,0.7683452645368496,-0.6324874733225441],"type":1,"volume":0.014400340208420098},{"fixed":false,"mass":0.017655656239148738,"nu":0,"particle_id":908,"point":[0.5879091870512756,0.448737393469377,0.8885729547273848],"type":1,"volume":0.017655656239148738},{"fixed":false,"mass":0.01793828437968264,"nu":0,"particle_id":909,"point":[0.3971667678031106,0.1870150801619561,0.9815806223058964],"type":1,"volume":0.01793828437968264},{"fixed":false,"mass":0.0170887787934123,"nu":0,"particle_id":910,"point":[5,0.449295900987054,-0.1377719299644467],"type":2,"volume":0.0170887787934123},{"fixed":false,"mass":0.018894093646532006,"nu":0,"particle_id":911,"point":[-4.527527950004503,0.7604588312474805,-0.6420971200899545],"type":1,"volume":0.018894093646532006},{"fixed":false,"mass":0.05176040981554773,"nu":0,"particle_id":912,"point":[2.839058548800647,-0.2533322565504474,-0.580638375505475],"type":1,"volume":0.05176040981554773},{"fixed":false,"mass":0.01979321789939595,"nu":0,"particle_id":913,"point":[0.3319953517398676,0.7990960811237033,0.5950174948967535],"type":1,"volume":0.01979321789939595},{"fixed":false,"mass":0.028922860379919667,"nu":0,"particle_id":914,"point":[-0.2031165366154546,-0.4588089938354433,-0.8831895721748764],"type":1,"volume":0.028922860379919667},{"fixed":false,"mass":0.007540242819340392,"nu":0,"particle_id":915,"point":[5,-0.3648174218556645,-0.9292991275486149],"type":2,"volume":0.007540242819340392},{"fixed":false,"mass":0.017371579095752935,"nu":0,"particle_id":916,"point":[5,-0.2928994367879654,-0.5157452132320554],"type":2,"volume":0.017371579095752935},{"fixed":false,"mass":0.013298723264750255,"nu":0,"particle_id":917,"point":[5,-0.6205144679482929,-0.778171256109975],"type":2,"volume":0.013298723264750255},{"fixed":false,"mass":0.014915044948456455,"nu":0,"particle_id":918,"point":[-5,-0.8754743362114682,-0.4732431850888849],"type":3,"volume":0.014915044948456455},{"fixed":false,"mass":0.027671370458642514,"nu":0,"particle_id":919,"point":[2.275974317405184,-0.6474624523098396,0.7560556168888711],"type":1,"volume":0.027671370458642514},{"fixed":false,"mass":0.010892520241565404,"nu":0,"particle_id":920,"point":[4.30157473621041,-0.7147242078120768,-0.6978249199874322],"type":1,"volume":0.010892520241565404},{"fixed":false,"mass":0.013523218802546253,"nu":0,"particle_id":921,"point":[-0.7995855620215795,-0.8206048260450199,0.5688090133791566],"type":1,"volume":0.013523218802546253},{"fixed":false,"mass":0.015513871180547728,"nu":0,"particle_id":922,"point":[-0.05464247259885766,0.8667620143490591,0.4895427928546083],"type":1,"volume":0.015513871180547728},{"fixed":false,"mass":0.015464217511409556,"nu":0,"particle_id":923,"point":[-1.326088918684652,0.8917268248518182,-0.4428369174786894],"type":1,"volume":0.015464217511409556},{"fixed":false,"mass":0.013439070984278592,"nu":0,"particle_id":924,"point":[-1.091917287969441,0.9518074985066813,-0.2906172668040216],"type":1,"volume":0.013439070984278592},{"fixed":false,"mass":0.02202344273674177,"nu":0,"particle_id":925,"point":[-1.56668683122494,-0.5455569851404194,-0.8368218048010045],"type":1,"volume":0.02202344273674177},{"fixed":false,"mass":0.017503390418905793,"nu":0,"particle_id":926,"point":[0.6270329530270939,0.06518996979417221,-0.9935793483901607],"type":1,"volume":0.017503390418905793},{"fixed":false,"mass":0.019146708066749094,"nu":0,"particle_id":927,"point":[2.468057117831111,-0.1746850259655029,0.982795026647175],"type":1,"volume":0.019146708066749094},{"fixed":false,"mass":0.026585669450483667,"nu":0,"particle_id":928,"point":[-2.584171198406722,0.7110837389103476,-0.7022608441789827],"type":1,"volume":0.026585669450483667},{"fixed":false,"mass":0.014780692143507105,"nu":0,"particle_id":929,"point":[-4.339723223550493,-0.7957762932357462,-0.5990626681424334],"type":1,"volume":0.014780692143507105},{"fixed":false,"mass":0.017890050561206468,"nu":0,"particle_id":930,"point":[5,-0.2303790259489255,0.4099653579356002],"type":2,"volume":0.017890050561206468},{"fixed":false,"mass":0.011740031035969992,"nu":0,"particle_id":931,"point":[5,0.4979412994680972,0.8622729190387929],"type":2,"volume":0.011740031035969992},{"fixed":false,"mass":0.017101155927670468,"nu":0,"particle_id":932,"point":[0.5067524745461469,-0.9531556491633695,-0.2861730096898309],"type":1,"volume":0.017101155927670468},{"fixed":false,"mass":0.01709011934971625,"nu":0,"particle_id":933,"point":[0.7723978277522143,-0.9841888401537169,0.1605333999450314],"type":1,"volume":0.01709011934971625},{"fixed":false,"mass":0.03842695162221376,"nu":0,"particle_id":934,"point":[3.510948687213142,0.04183444396393932,0.6610923674129817],"type":1,"volume":0.03842695162221376},{"fixed":false,"mass":0.01439673458221944,"nu":0,"particle_id":935,"point":[4.363494735650864,0.8254937487210299,0.5628518438621128],"type":1,"volume":0.01439673458221944},{"fixed":false,"mass":0.016670330687456585,"nu":0,"particle_id":936,"point":[-3.025257855722505,0.9814017653359453,0.1888310454528824],"type":1,"volume":0.016670330687456585},{"fixed":false,"mass":0.02002641727319202,"nu":0,"particle_id":937,"point":[-1.271902236156503,-0.5506122792360834,0.8341196938113655],"type":1,"volume":0.02002641727319202},{"fixed":false,"mass":0.015906407839648806,"nu":0,"particle_id":938,"point":[4.580847897476351,0.9509856974164279,-0.2933263819342119],"type":1,"volume":0.015906407839648806},{"fixed":false,"mass":0.0190412149588889,"nu":0,"particle_id":939,"point":[5,0.8974766981659327,-0.4320796611235209],"type":2,"volume":0.0190412149588889},{"fixed":false,"mass":0.020139544679042838,"nu":0,"particle_id":940,"point":[4.526966716208524,0.8271036679545477,-0.5608901516001582],"type":1,"volume":0.020139544679042838},{"fixed":false,"mass":0.006364857660482268,"nu":0,"particle_id":941,"point":[-5,0.6565945984642336,-0.7485610582252125],"type":3,"volume":0.006364857660482268},{"fixed":false,"mass":0.01692233171531006,"nu":0,"particle_id":942,"point":[-5,0.5882179477292848,-0.06010530840869419],"type":3,"volume":0.01692233171531006},{"fixed":false,"mass":0.018917082637016462,"nu":0,"particle_id":943,"point":[-5,0.4074084651670587,0.219319243420286],"type":3,"volume":0.018917082637016462},{"fixed":false,"mass":0.011016599252804094,"nu":0,"particle_id":944,"point":[5,0.1779918422150383,-0.2210388615188594],"type":2,"volume":0.011016599252804094},{"fixed":false,"mass":0.011015413922088794,"nu":0,"particle_id":945,"point":[4.227243727968061,0.825493748721031,-0.5628518438621098],"type":1,"volume":0.011015413922088794},{"fixed":false,"mass":0.014767331294081455,"nu":0,"particle_id":946,"point":[4.085610236382966,0.3646659590504697,0.9293450732882533],"type":1,"volume":0.014767331294081455},{"fixed":false,"mass":0.01335891465075578,"nu":0,"particle_id":947,"point":[-4.363025176117931,0.6998251703440379,0.7130826447680633],"type":1,"volume":0.01335891465075578},{"fixed":false,"mass":0.01161382951238689,"nu":0,"particle_id":948,"point":[-1.356877094646717,-0.2546145637265111,0.962728799086144],"type":1,"volume":0.01161382951238689},{"fixed":false,"mass":0.022832082116180066,"nu":0,"particle_id":949,"point":[-1.037072523066932,-0.161636974820295,0.9840801475155425],"type":1,"volume":0.022832082116180066},{"fixed":false,"mass":0.01643909808659953,"nu":0,"particle_id":950,"point":[1.109879798912506,0.5031144331794252,-0.8595078214623257],"type":1,"volume":0.01643909808659953},{"fixed":false,"mass":0.02988892559912434,"nu":0,"particle_id":951,"point":[-1.766940242041527,0.05657010767494611,0.3165516912135875],"type":1,"volume":0.02988892559912434},{"fixed":false,"mass":0.025142600118914837,"nu":0,"particle_id":952,"point":[3.03091997311019,0.4599800862076042,0.8825636102607295],"type":1,"volume":0.025142600118914837},{"fixed":false,"mass":0.014856731968742638,"nu":0,"particle_id":953,"point":[1.837827369481052,0.2267617827318211,0.9711778478301247],"type":1,"volume":0.014856731968742638},{"fixed":false,"mass":0.009296185771006554,"nu":0,"particle_id":954,"point":[-1.078950880825758,-0.2792100091359183,-0.955267852289355],"type":1,"volume":0.009296185771006554},{"fixed":false,"mass":0.022163174080120585,"nu":0,"particle_id":955,"point":[1.839155068427205,-0.5993555883812759,0.7955358998083237],"type":1,"volume":0.022163174080120585},{"fixed":false,"mass":0.015079115048246324,"nu":0,"particle_id":956,"point":[0.4916764545431682,0.9872598502099428,-0.1293529115821105],"type":1,"volume":0.015079115048246324},{"fixed":false,"mass":0.013801498231326554,"nu":0,"particle_id":957,"point":[-3.601686628168117,-0.1492013763129316,0.9853049470641191],"type":1,"volume":0.013801498231326554},{"fixed":false,"mass":0.0279062630642977,"nu":0,"particle_id":958,"point":[-0.2496633002004731,-0.1101098237825397,-0.3382155573050047],"type":1,"volume":0.0279062630642977},{"fixed":false,"mass":0.011120570088805567,"nu":0,"particle_id":959,"point":[4.125440368486037,0.0857827825630609,0.9915511333614816],"type":1,"volume":0.011120570088805567},{"fixed":false,"mass":0.004748023527992474,"nu":0,"particle_id":960,"point":[-5,-0.1765102913479226,-0.9826152536981612],"type":3,"volume":0.004748023527992474},{"fixed":false,"mass":0.00873378582331316,"nu":0,"particle_id":961,"point":[-5,0.1207701993433182,-0.9881051735829521],"type":3,"volume":0.00873378582331316},{"fixed":false,"mass":0.02399406272353588,"nu":0,"particle_id":962,"point":[1.536503746062925,-0.08411596179335432,0.9917153008782351],"type":1,"volume":0.02399406272353588},{"fixed":false,"mass":0.028505751372817946,"nu":0,"particle_id":963,"point":[1.735903681555198,0.9915392045582637,0.08590389773465265],"type":1,"volume":0.028505751372817946},{"fixed":false,"mass":0.012543724824608844,"nu":0,"particle_id":964,"point":[5,0.7307949394943577,-0.6782426767737948],"type":2,"volume":0.012543724824608844},{"fixed":false,"mass":0.017141616053507655,"nu":0,"particle_id":965,"point":[-3.840538358117914,0.8754876355926591,0.4732183036967188],"type":1,"volume":0.017141616053507655},{"fixed":false,"mass":0.015354217549660954,"nu":0,"particle_id":966,"point":[-5,-0.2441762422722216,-0.1745870161189224],"type":3,"volume":0.015354217549660954},{"fixed":false,"mass":0.009567470102835911,"nu":0,"particle_id":967,"point":[-5,-0.1455277744685972,-0.4457664316020963],"type":3,"volume":0.009567470102835911},{"fixed":false,"mass":0.009351458776675864,"nu":0,"particle_id":968,"point":[-5,-0.2168065382133226,-0.6489098659443657],"type":3,"volume":0.009351458776675864},{"fixed":false,"mass":0.011663762722754135,"nu":0,"particle_id":969,"point":[4.124937999039393,-0.4977671297229378,-0.8623660147071348],"type":1,"volume":0.011663762722754135},{"fixed":false,"mass":0.0064862038247827936,"nu":0,"particle_id":970,"point":[-4.646697831024541,0.6998251703440376,0.7130826447680636],"type":1,"volume":0.0064862038247827936},{"fixed":false,"mass":0.01157614839615208,"nu":0,"particle_id":971,"point":[-5,0.584434337432353,0.8077814539947368],"type":3,"volume":0.01157614839615208},{"fixed":false,"mass":0.014339171647622665,"nu":0,"particle_id":972,"point":[4.167131656990855,-0.4977671297229396,0.8623660147071255],"type":1,"volume":0.014339171647622665},{"fixed":false,"mass":0.03955799359845271,"nu":0,"particle_id":973,"point":[-3.383132852142184,-0.5964337559078083,-0.3136038018618766],"type":1,"volume":0.03955799359845271},{"fixed":false,"mass":0.016636441686453347,"nu":0,"particle_id":974,"point":[-3.502003745080589,0.1631585178551935,0.9839302886067669],"type":1,"volume":0.016636441686453347},{"fixed":false,"mass":0.025563172703745765,"nu":0,"particle_id":975,"point":[3.266669947298161,0.7636315508710978,0.6382311500428738],"type":1,"volume":0.025563172703745765},{"fixed":false,"mass":0.01078600848180496,"nu":0,"particle_id":976,"point":[-0.943619219313441,0.2656273929842567,-0.9593880938536729],"type":1,"volume":0.01078600848180496},{"fixed":false,"mass":0.014873436457016715,"nu":0,"particle_id":977,"point":[-1.529902565350081,0.9430791026421824,0.3193909318419983],"type":1,"volume":0.014873436457016715},{"fixed":false,"mass":0.00902457961238819,"nu":0,"particle_id":978,"point":[-1.982384169879702,0.6161730157820616,-0.7817341938241981],"type":1,"volume":0.00902457961238819},{"fixed":false,"mass":0.00925848404412511,"nu":0,"particle_id":979,"point":[3.677481968307688,0.9977315879499924,0.02303157405303171],"type":1,"volume":0.00925848404412511},{"fixed":false,"mass":0.012119597352368228,"nu":0,"particle_id":980,"point":[-2.212051260567566,0.9039280545498317,-0.4200100222516882],"type":1,"volume":0.012119597352368228},{"fixed":false,"mass":0.017861087698817706,"nu":0,"particle_id":981,"point":[-0.344841364631034,-0.06703191467103983,0.9933979326543318],"type":1,"volume":0.017861087698817706},{"fixed":false,"mass":0.01841320785948885,"nu":0,"particle_id":982,"point":[-3.38698597749798,0.4994438909225991,-0.8614697671735772],"type":1,"volume":0.01841320785948885},{"fixed":false,"mass":0.008397107962555609,"nu":0,"particle_id":983,"point":[-3.107479011044399,0.4858933071279471,-0.8687127051104528],"type":1,"volume":0.008397107962555609},{"fixed":false,"mass":0.016381252106837843,"nu":0,"particle_id":984,"point":[-0.4411892322856439,0.9834839450543891,0.1676903199938978],"type":1,"volume":0.016381252106837843},{"fixed":false,"mass":0.017696108316589992,"nu":0,"particle_id":985,"point":[-0.3736647980878536,0.8806709631755958,0.4635209798538455],"type":1,"volume":0.017696108316589992},{"fixed":false,"mass":0.009848429503069182,"nu":0,"particle_id":986,"point":[-5,0.8490715018661168,-0.5226394138473112],"type":3,"volume":0.009848429503069182},{"fixed":false,"mass":0.011682325829434778,"nu":0,"particle_id":987,"point":[-5,0.9645264952912471,-0.2486883535444012],"type":3,"volume":0.011682325829434778},{"fixed":false,"mass":0.01761535949737005,"nu":0,"particle_id":988,"point":[-1.201143646140392,-0.9836878489271653,0.1656200492309055],"type":1,"volume":0.01761535949737005},{"fixed":false,"mass":0.03138144205038209,"nu":0,"particle_id":989,"point":[-1.112139267602656,0.02023541635997546,0.3897646838745212],"type":1,"volume":0.03138144205038209},{"fixed":false,"mass":0.020954543507588106,"nu":0,"particle_id":990,"point":[-2.161383284366988,0.696611058009545,0.7157203985923224],"type":1,"volume":0.020954543507588106},{"fixed":false,"mass":0.016066141011998287,"nu":0,"particle_id":991,"point":[-2.292481192811842,0.9339800299948684,0.3493865544712289],"type":1,"volume":0.016066141011998287},{"fixed":false,"mass":0.021374237113973193,"nu":0,"particle_id":992,"point":[3.104657000610138,0.5601944060992201,-0.8276746515309821],"type":1,"volume":0.021374237113973193},{"fixed":false,"mass":0.017944942907841387,"nu":0,"particle_id":993,"point":[2.610442561368638,-0.006016093087303043,-0.9994074665491042],"type":1,"volume":0.017944942907841387},{"fixed":false,"mass":0.006603123699998064,"nu":0,"particle_id":994,"point":[5,0.2218893377802632,0.9726558878472392],"type":2,"volume":0.006603123699998064},{"fixed":false,"mass":0.008281972193445107,"nu":0,"particle_id":995,"point":[-5,0.06982731638799593,-0.259822573245374],"type":3,"volume":0.008281972193445107},{"fixed":false,"mass":0.022820701595591273,"nu":0,"particle_id":996,"point":[-2.368167634263179,0.4205863284215421,0.9036200124843283],"type":1,"volume":0.022820701595591273},{"fixed":false,"mass":0.014522575376168486,"nu":0,"particle_id":997,"point":[3.672323183772062,-0.2070190066272035,0.9771667534866637],"type":1,"volume":0.014522575376168486},{"fixed":false,"mass":0.02725849665387228,"nu":0,"particle_id":998,"point":[3.73266771130354,-0.5002540417851093,0.8610367325157655],"type":1,"volume":0.02725849665387228},{"fixed":false,"mass":0.01855724061291899,"nu":0,"particle_id":999,"point":[0.1613098429978297,-0.9948720221109452,-0.05206523325146501],"type":1,"volume":0.01855724061291899},{"fixed":false,"mass":0.05132624302976354,"nu":0,"particle_id":1000,"point":[0.2413194306166689,-0.6225435975184763,0.2017239799100479],"type":1,"volume":0.05132624302976354},{"fixed":false,"mass":0.018012146219832027,"nu":0,"particle_id":1001,"point":[1.372882095137661,0.2993615974934478,-0.9491549347916788],"type":1,"volume":0.018012146219832027},{"fixed":false,"mass":0.01482971192504359,"nu":0,"particle_id":1002,"point":[0.4339759092147741,-0.9993430575433229,0.006670048697497093],"type":1,"volume":0.01482971192504359},{"fixed":false,"mass":0.012919658524484083,"nu":0,"particle_id":1003,"point":[0.3569514390370192,-0.8705465415691376,0.4824624404250055],"type":1,"volume":0.012919658524484083},{"fixed":false,"mass":0.023632931056365616,"nu":0,"particle_id":1004,"point":[-2.493479014048914,0.9978688878246185,0.02163754503175582],"type":1,"volume":0.023632931056365616},{"fixed":false,"mass":0.018932898574820608,"nu":0,"particle_id":1005,"point":[2.189691001906279,0.9816693826705685,0.1861138810557748],"type":1,"volume":0.018932898574820608},{"fixed":false,"mass":0.0059562746539401105,"nu":0,"particle_id":1006,"point":[4.700502539162661,-0.2221001761570676,-0.9725919307248585],"type":1,"volume":0.0059562746539401105},{"fixed":false,"mass":0.00891649219076992,"nu":0,"particle_id":1007,"point":[5,-0.0743201226728102,-0.9926801068202783],"type":2,"volume":0.00891649219076992},{"fixed":false,"mass":0.017392144988072275,"nu":0,"particle_id":1008,"point":[-1.016597024252175,0.005510379442670473,-0.9994572749956608],"type":1,"volume":0.017392144988072275},{"fixed":false,"mass":0.018316003466602275,"nu":0,"particle_id":1009,"point":[0.6210448425873312,0.935611875618706,0.3440070803842459],"type":1,"volume":0.018316003466602275},{"fixed":false,"mass":0.01857439599372155,"nu":0,"particle_id":1010,"point":[0.6637445625703706,0.769040573326093,0.6316402371114785],"type":1,"volume":0.01857439599372155},{"fixed":false,"mass":0.004965992767567558,"nu":0,"particle_id":1011,"point":[5,0.4979412994680995,-0.8622729190387917],"type":2,"volume":0.004965992767567558},{"fixed":false,"mass":0.03247257858543052,"nu":0,"particle_id":1012,"point":[-1.02166282382571,0.09552591792739831,0.6931447527655266],"type":1,"volume":0.03247257858543052},{"fixed":false,"mass":0.019788961121925658,"nu":0,"particle_id":1013,"point":[-0.2335848473453115,-0.4952143085965474,0.8637305260272723],"type":1,"volume":0.019788961121925658},{"fixed":false,"mass":0.01231697559821552,"nu":0,"particle_id":1014,"point":[3.301892205796323,0.8628236125692176,-0.4969110243374485],"type":1,"volume":0.01231697559821552},{"fixed":false,"mass":0.028593405599732016,"nu":0,"particle_id":1015,"point":[1.810536990236975,0.8919924324646697,0.4423400005858739],"type":1,"volume":0.028593405599732016},{"fixed":false,"mass":0.008207144389310219,"nu":0,"particle_id":1016,"point":[0.9555688169141461,0.3251786111121515,0.9413234293297981],"type":1,"volume":0.008207144389310219},{"fixed":false,"mass":0.009225087270246018,"nu":0,"particle_id":1017,"point":[-3.723152817159582,-0.9622695618398647,0.2561284660405836],"type":1,"volume":0.009225087270246018},{"fixed":false,"mass":0.01660565267815375,"nu":0,"particle_id":1018,"point":[-3.980497948181937,-0.9051315325751712,0.4177584732297981],"type":1,"volume":0.01660565267815375},{"fixed":false,"mass":0.013740708500435708,"nu":0,"particle_id":1019,"point":[-1.290049340381032,0.6972474095936946,-0.7151981583437006],"type":1,"volume":0.013740708500435708},{"fixed":false,"mass":0.0075092713848055916,"nu":0,"particle_id":1020,"point":[4.112426786755465,-0.9227720027163318,0.3847554748735866],"type":1,"volume":0.0075092713848055916},{"fixed":false,"mass":0.01703554034389921,"nu":0,"particle_id":1021,"point":[-3.540820465114851,-0.999101886207592,0.009118702361780114],"type":1,"volume":0.01703554034389921},{"fixed":false,"mass":0.006964364711383569,"nu":0,"particle_id":1022,"point":[-5,0.9954250667626737,0.04645007667050866],"type":3,"volume":0.006964364711383569},{"fixed":false,"mass":0.014385596533002315,"nu":0,"particle_id":1023,"point":[-3.897565509429982,-0.2867448152637051,0.9529821938388665],"type":1,"volume":0.014385596533002315},{"fixed":false,"mass":0.01035807121332118,"nu":0,"particle_id":1024,"point":[1.215681715135308,0.4026863588416098,0.9131877455579819],"type":1,"volume":0.01035807121332118},{"fixed":false,"mass":0.009769861270907825,"nu":0,"particle_id":1025,"point":[0.7590240831048151,0.141265010020894,0.9860866109177782],"type":1,"volume":0.009769861270907825},{"fixed":false,"mass":0.013981167538005606,"nu":0,"particle_id":1026,"point":[3.559460892036901,0.9529435732543861,-0.2868721302685079],"type":1,"volume":0.013981167538005606},{"fixed":false,"mass":0.02349557872856551,"nu":0,"particle_id":1027,"point":[-3.283069293434385,0.6507451006875258,0.7533616169875559],"type":1,"volume":0.02349557872856551},{"fixed":false,"mass":0.016989957711702815,"nu":0,"particle_id":1028,"point":[-5,0.2734215739068337,0.5253203130299532],"type":3,"volume":0.016989957711702815},{"fixed":false,"mass":0.016638305647799723,"nu":0,"particle_id":1029,"point":[-3.276976891908061,-0.9639715459539244,-0.2505177763378972],"type":1,"volume":0.016638305647799723},{"fixed":false,"mass":0.00900476140405003,"nu":0,"particle_id":1030,"point":[0.1670776802986834,-0.9714554564104547,0.225846629887463],"type":1,"volume":0.00900476140405003},{"fixed":false,"mass":0.005915954675994636,"nu":0,"particle_id":1031,"point":[-0.7176233233654546,0.9434934460111863,-0.3180250248075879],"type":1,"volume":0.005915954675994636},{"fixed":false,"mass":0.013450063661136737,"nu":0,"particle_id":1032,"point":[0.9799598183595095,0.7417118864481768,-0.6649403384219092],"type":1,"volume":0.013450063661136737},{"fixed":false,"mass":0.010032970568193186,"nu":0,"particle_id":1033,"point":[1.387245277489384,0.9224073529924759,0.3854376865233187],"type":1,"volume":0.010032970568193186},{"fixed":false,"mass":0.005949045146047745,"nu":0,"particle_id":1034,"point":[-2.057242895266359,0.7960216541923506,-0.5987636949517685],"type":1,"volume":0.005949045146047745},{"fixed":false,"mass":0.011255192264081304,"nu":0,"particle_id":1035,"point":[-3.309153638293909,0.3930180628342507,0.9183555574395839],"type":1,"volume":0.011255192264081304},{"fixed":false,"mass":0.013895953148563421,"nu":0,"particle_id":1036,"point":[-1.348798025386405,0.4415104789011309,-0.8924358210426773],"type":1,"volume":0.013895953148563421},{"fixed":false,"mass":0.009243383564207676,"nu":0,"particle_id":1037,"point":[-4.625357468721793,0.9164034369759859,-0.396670223345604],"type":1,"volume":0.009243383564207676},{"fixed":false,"mass":0.019472056453767723,"nu":0,"particle_id":1038,"point":[-2.0127287757599,-0.4533784759674835,-0.8860922444492805],"type":1,"volume":0.019472056453767723},{"fixed":false,"mass":0.01053709132402127,"nu":0,"particle_id":1039,"point":[-5,-0.7604051373791183,0.6421625462578562],"type":3,"volume":0.01053709132402127},{"fixed":false,"mass":0.014012175570071533,"nu":0,"particle_id":1040,"point":[0.8194661920390395,-0.9881238204969696,-0.1205808740480965],"type":1,"volume":0.014012175570071533},{"fixed":false,"mass":0.014221355627230196,"nu":0,"particle_id":1041,"point":[-1.579920744404556,0.3329641709816509,-0.9389617055633595],"type":1,"volume":0.014221355627230196},{"fixed":false,"mass":0.010922667161967879,"nu":0,"particle_id":1042,"point":[-1.573150465218438,0.5564926431155143,-0.830712609900384],"type":1,"volume":0.010922667161967879},{"fixed":false,"mass":0.015846093645865294,"nu":0,"particle_id":1043,"point":[-4.639402369226559,-0.7899213520790904,-0.6061969345839286],"type":1,"volume":0.015846093645865294},{"fixed":false,"mass":0.01598580651581511,"nu":0,"particle_id":1044,"point":[-1.749489556373944,0.7021987255644131,-0.7111347183398407],"type":1,"volume":0.01598580651581511},{"fixed":false,"mass":0.004761896249862649,"nu":0,"particle_id":1045,"point":[-3.021734139942147,-0.9409091115683528,-0.3265444337297547],"type":1,"volume":0.004761896249862649},{"fixed":false,"mass":0.011548125721064733,"nu":0,"particle_id":1046,"point":[-1.55561753735395,0.8222968814728506,-0.5667472378748547],"type":1,"volume":0.011548125721064733},{"fixed":false,"mass":0.018380178069471342,"nu":0,"particle_id":1047,"point":[2.022423120467987,-0.1262354888433054,0.9875668895503452],"type":1,"volume":0.018380178069471342},{"fixed":false,"mass":0.01067799249785435,"nu":0,"particle_id":1048,"point":[-2.862954416515959,0.9899379122074038,-0.1021620918133078],"type":1,"volume":0.01067799249785435},{"fixed":false,"mass":0.008733230980521962,"nu":0,"particle_id":1049,"point":[1.246847026688676,0.8101232211797889,0.5815808858612608],"type":1,"volume":0.008733230980521962},{"fixed":false,"mass":0.018834907107490573,"nu":0,"particle_id":1050,"point":[1.991238425976736,0.4139884339489344,0.907146660553765],"type":1,"volume":0.018834907107490573},{"fixed":false,"mass":0.006108475999075238,"nu":0,"particle_id":1051,"point":[-1.078983625684152,0.4850161335979228,-0.8691815641304121],"type":1,"volume":0.006108475999075238},{"fixed":false,"mass":0.016409856849851724,"nu":0,"particle_id":1052,"point":[-0.08867280886313098,0.8455127545741612,-0.5292973617413717],"type":1,"volume":0.016409856849851724},{"fixed":false,"mass":0.0107893580170935,"nu":0,"particle_id":1053,"point":[-1.360185774692487,-0.7117886848740509,-0.7014018650368614],"type":1,"volume":0.0107893580170935},{"fixed":false,"mass":0.01145410519412495,"nu":0,"particle_id":1054,"point":[0.5198823332627864,-0.9599732301422427,0.2636984571488241],"type":1,"volume":0.01145410519412495},{"fixed":false,"mass":0.011886562217206489,"nu":0,"particle_id":1055,"point":[2.222944519093411,0.3254521988863885,0.9412404373858082],"type":1,"volume":0.011886562217206489},{"fixed":false,"mass":0.013683452863685582,"nu":0,"particle_id":1056,"point":[0.5680000480319429,-0.017274607018516,0.9982985997123028],"type":1,"volume":0.013683452863685582},{"fixed":false,"mass":0.016742165371781137,"nu":0,"particle_id":1057,"point":[2.373995485045244,0.09175352030398484,0.9909630670223006],"type":1,"volume":0.016742165371781137},{"fixed":false,"mass":0.021206067595278093,"nu":0,"particle_id":1058,"point":[-2.998080836239336,0.9274268869274227,-0.3709893720445633],"type":1,"volume":0.021206067595278093},{"fixed":false,"mass":0.019691557222636685,"nu":0,"particle_id":1059,"point":[3.285570800672676,0.7069732768365413,-0.7072163453750809],"type":1,"volume":0.019691557222636685}],"rho_0":1,"size":null,"types":[{"fixed":false,"mass":1,"name":"Un-Assigned","nu":0,"typeID":0,"volume":1},{"fixed":false,"mass":1,"name":"Middle","nu":0,"typeID":1,"volume":1},{"fixed":false,"mass":1,"name":"Edge 1","nu":0,"typeID":2,"volume":1},{"fixed":false,"mass":1,"name":"Edge 2","nu":0,"typeID":3,"volume":1}],"x_lim":[-5,5],"y_lim":[-1,0.9999999999999999],"z_lim":[-0.9997191433003008,0.9999488265847117]},"eventsCollection":[],"functionDefinitions":[],"initialConditions":[],"is_spatial":true,"modelSettings":{"endSim":500,"timeStep":1},"parameters":[{"compID":3,"expression":1,"name":"k_react"},{"compID":4,"expression":196.38595510240296,"name":"k_creat1"},{"compID":5,"expression":197.70475491603773,"name":"k_creat2"}],"reactions":[{"annotation":"","compID":6,"massaction":true,"name":"r1","products":[{"ratio":1,"specie":{"annotation":"","compId":1,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"A","switchMin":100,"switchTol":0.03,"types":[1,2],"value":0}}],"propensity":"","rate":{"compID":4,"expression":196.38595510240296,"name":"k_creat1"},"reactants":[],"reactionType":"creation","summary":"\\emptyset \\rightarrow A","types":[2]},{"annotation":"","compID":7,"massaction":true,"name":"r2","products":[{"ratio":1,"specie":{"annotation":"","compId":2,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"B","switchMin":100,"switchTol":0.03,"types":[1,3],"value":0}}],"propensity":"","rate":{"compID":5,"expression":197.70475491603773,"name":"k_creat2"},"reactants":[],"reactionType":"creation","summary":"\\emptyset \\rightarrow B","types":[3]},{"annotation":"","compID":8,"massaction":true,"name":"r3","products":[],"propensity":"","rate":{"compID":3,"expression":1,"name":"k_react"},"reactants":[{"ratio":1,"specie":{"annotation":"","compId":1,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"A","switchMin":100,"switchTol":0.03,"types":[1,2],"value":0}},{"ratio":1,"specie":{"annotation":"","compId":2,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"B","switchMin":100,"switchTol":0.03,"types":[1,3],"value":0}}],"reactionType":"custom-massaction","summary":"A + B \\rightarrow \\emptyset","types":[1,2,3]}],"rules":[],"species":[{"annotation":"","compId":1,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"A","switchMin":100,"switchTol":0.03,"types":[1,2],"value":0,"diffusionConst":0.1},{"annotation":"","compId":2,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"B","switchMin":100,"switchTol":0.03,"types":[1,3],"value":0,"diffusionConst":0.1}],"volume":1,"name":"cylinder_demo3d"} \ No newline at end of file +{"annotation":"SpatialPy 3D Cylinder Demo Model","defaultID":9,"defaultMode":"discrete","domain":{"boundary_condition":{"reflect_x":true,"reflect_y":true,"reflect_z":true},"c_0":10,"gravity":[0, 0, 0],"p_0":10,"particles":[{"fixed":false,"mass":0.015135255135374578,"nu":0,"particle_id":1,"point":[-2.101682616989703,-0.964452787824742,0.2489313344981683],"type":1,"volume":0.015135255135374578},{"fixed":false,"mass":0.07034111605740352,"nu":0,"particle_id":2,"point":[-1.887513465434122,-0.5014916255865332,0.06961314329212905],"type":1,"volume":0.07034111605740352},{"fixed":false,"mass":0.02382667425447659,"nu":0,"particle_id":3,"point":[-1.757042722631912,-0.9228641348563182,0.3845831077631754],"type":1,"volume":0.02382667425447659},{"fixed":false,"mass":0.01837175522796916,"nu":0,"particle_id":4,"point":[-1.85413888369328,-0.9955594999585697,0.04508515352682077],"type":1,"volume":0.01837175522796916},{"fixed":false,"mass":0.04863919527628578,"nu":0,"particle_id":5,"point":[1.874975500982107,0.2492223157132696,-0.2524856754824046],"type":1,"volume":0.04863919527628578},{"fixed":false,"mass":0.0632175288192508,"nu":0,"particle_id":6,"point":[1.808320438516406,0.05711590686461099,-0.6164182499126918],"type":1,"volume":0.0632175288192508},{"fixed":false,"mass":0.05566341760973872,"nu":0,"particle_id":7,"point":[2.182529343210714,-0.1663114027612958,-0.4557993633541657],"type":1,"volume":0.05566341760973872},{"fixed":false,"mass":0.05094615682555442,"nu":0,"particle_id":8,"point":[2.06222242502517,-0.06584170406028653,-0.09390309609504216],"type":1,"volume":0.05094615682555442},{"fixed":false,"mass":0.027613011065781377,"nu":0,"particle_id":9,"point":[-2.380044639472586,0.1039603942187995,-0.6660021716554381],"type":1,"volume":0.027613011065781377},{"fixed":false,"mass":0.043631235211839,"nu":0,"particle_id":10,"point":[-2.305676947241498,-0.3113331410231057,-0.589095101307394],"type":1,"volume":0.043631235211839},{"fixed":false,"mass":0.02307565554258796,"nu":0,"particle_id":11,"point":[-2.262942990799641,-0.04111516086018868,-0.9959505101076245],"type":1,"volume":0.02307565554258796},{"fixed":false,"mass":0.053285055209458865,"nu":0,"particle_id":12,"point":[-2.093631369619373,-0.04820563757950643,-0.6060599358098253],"type":1,"volume":0.053285055209458865},{"fixed":false,"mass":0.013863453851301994,"nu":0,"particle_id":13,"point":[-1.999792859336622,-0.94943344706238,-0.2984434655811745],"type":1,"volume":0.013863453851301994},{"fixed":false,"mass":0.006452758616580852,"nu":0,"particle_id":14,"point":[-1.754728853599724,-0.8801338975074484,-0.464525759047439],"type":1,"volume":0.006452758616580852},{"fixed":false,"mass":0.06319118564277616,"nu":0,"particle_id":15,"point":[-1.689826608177531,-0.5981799589653591,-0.2304829208262158],"type":1,"volume":0.06319118564277616},{"fixed":false,"mass":0.012063450996053436,"nu":0,"particle_id":16,"point":[-1.670428874777768,-0.9736314258341583,-0.2186734200213536],"type":1,"volume":0.012063450996053436},{"fixed":false,"mass":0.06390075032081181,"nu":0,"particle_id":17,"point":[3.590501737794977,-0.4310110060573188,-0.3131780598352483],"type":1,"volume":0.06390075032081181},{"fixed":false,"mass":0.03900782913147994,"nu":0,"particle_id":18,"point":[3.257879943487412,-0.4243756833306612,0.07732536880979513],"type":1,"volume":0.03900782913147994},{"fixed":false,"mass":0.07191513330511291,"nu":0,"particle_id":19,"point":[3.160881489131067,-0.4731490872585901,-0.3414347939235592],"type":1,"volume":0.07191513330511291},{"fixed":false,"mass":0.03889328117454658,"nu":0,"particle_id":20,"point":[3.4964304507652,-0.6577183471508495,-0.05248579623331021],"type":1,"volume":0.03889328117454658},{"fixed":false,"mass":0.03917814937239849,"nu":0,"particle_id":21,"point":[-0.6913178542741429,0.2146395970789712,-0.1038293381612584],"type":1,"volume":0.03917814937239849},{"fixed":false,"mass":0.06467136826869545,"nu":0,"particle_id":22,"point":[-1.044361330579384,0.5974390889571882,-0.01981372633389583],"type":1,"volume":0.06467136826869545},{"fixed":false,"mass":0.03678980262339302,"nu":0,"particle_id":23,"point":[-0.8108570256428013,0.2125028850865174,0.2175561585244626],"type":1,"volume":0.03678980262339302},{"fixed":false,"mass":0.040413057773667674,"nu":0,"particle_id":24,"point":[-0.5850074823172771,0.433377778775099,0.1301490585358179],"type":1,"volume":0.040413057773667674},{"fixed":false,"mass":0.04369920752229525,"nu":0,"particle_id":25,"point":[-0.2936847104329262,0.4884589904276384,0.405308684893338],"type":1,"volume":0.04369920752229525},{"fixed":false,"mass":0.019707836516532865,"nu":0,"particle_id":26,"point":[0.06755331827299763,0.6967326601039996,0.7156206023324831],"type":1,"volume":0.019707836516532865},{"fixed":false,"mass":0.0229023521723117,"nu":0,"particle_id":27,"point":[-0.2711331659044802,0.6029126244346361,0.792616715761118],"type":1,"volume":0.0229023521723117},{"fixed":false,"mass":0.05884538686747711,"nu":0,"particle_id":28,"point":[0.01874290730254941,0.2368088283033387,0.4570474213646968],"type":1,"volume":0.05884538686747711},{"fixed":false,"mass":0.03421042879504796,"nu":0,"particle_id":29,"point":[4.43058544654569,0.6917465481935645,-0.1318762867133248],"type":1,"volume":0.03421042879504796},{"fixed":false,"mass":0.05344933653752932,"nu":0,"particle_id":30,"point":[4.508673766283515,0.4850515259508832,0.1265351969117867],"type":1,"volume":0.05344933653752932},{"fixed":false,"mass":0.0541141059782541,"nu":0,"particle_id":31,"point":[4.325610933271159,0.1837641403320487,-0.228199869286026],"type":1,"volume":0.0541141059782541},{"fixed":false,"mass":0.05523181637938297,"nu":0,"particle_id":32,"point":[4.611989612137674,0.4816263712555289,-0.3281902004283623],"type":1,"volume":0.05523181637938297},{"fixed":false,"mass":0.03254264921165492,"nu":0,"particle_id":33,"point":[3.433864759691629,-0.6320042529451704,0.2801340391076638],"type":1,"volume":0.03254264921165492},{"fixed":false,"mass":0.014880838966590903,"nu":0,"particle_id":34,"point":[3.488844898689435,-0.7730604064130339,0.6267420563227659],"type":1,"volume":0.014880838966590903},{"fixed":false,"mass":0.015892280530313798,"nu":0,"particle_id":35,"point":[3.289395677680728,-0.915443716604872,0.3984657338720717],"type":1,"volume":0.015892280530313798},{"fixed":false,"mass":0.017242446554284085,"nu":0,"particle_id":36,"point":[3.620442983847549,-0.9334678696573689,0.3510749208361043],"type":1,"volume":0.017242446554284085},{"fixed":false,"mass":0.017319408013948448,"nu":0,"particle_id":37,"point":[3.711388702989438,-0.9376186091765497,-0.3373917664009833],"type":1,"volume":0.017319408013948448},{"fixed":false,"mass":0.03942973229567603,"nu":0,"particle_id":38,"point":[3.857684954996952,-0.6324880361221572,-0.188173657943937],"type":1,"volume":0.03942973229567603},{"fixed":false,"mass":0.01060732084260641,"nu":0,"particle_id":39,"point":[3.974630202682578,-0.9645949697573137,-0.2484626234811865],"type":1,"volume":0.01060732084260641},{"fixed":false,"mass":0.018929906757140968,"nu":0,"particle_id":40,"point":[4.00385419870279,-0.8584909334426989,-0.5050168968536721],"type":1,"volume":0.018929906757140968},{"fixed":false,"mass":0.05111105459146263,"nu":0,"particle_id":41,"point":[-3.91324743689939,-0.02166296556491133,-0.5259588911325391],"type":1,"volume":0.05111105459146263},{"fixed":false,"mass":0.026733958029860273,"nu":0,"particle_id":42,"point":[-4.006449890432997,-0.1991719033668591,-0.2677197590261951],"type":1,"volume":0.026733958029860273},{"fixed":false,"mass":0.0611103943896377,"nu":0,"particle_id":43,"point":[-3.827309721067169,-0.4061733865595524,-0.4464451220022018],"type":1,"volume":0.0611103943896377},{"fixed":false,"mass":0.04955771362005426,"nu":0,"particle_id":44,"point":[-3.709832170994791,0.01375947885433382,-0.2486591502968405],"type":1,"volume":0.04955771362005426},{"fixed":false,"mass":0.0358926616277714,"nu":0,"particle_id":45,"point":[2.300184183244939,0.6443992069322578,0.2480498447961973],"type":1,"volume":0.0358926616277714},{"fixed":false,"mass":0.04048944903124158,"nu":0,"particle_id":46,"point":[2.291455805268016,0.2646108744755237,0.1827930918194401],"type":1,"volume":0.04048944903124158},{"fixed":false,"mass":0.04198381930621172,"nu":0,"particle_id":47,"point":[2.005228419850228,0.3110242200383387,0.03786000734078365],"type":1,"volume":0.04198381930621172},{"fixed":false,"mass":0.046019658028041824,"nu":0,"particle_id":48,"point":[2.262811974025447,0.4987179567116687,-0.07831154307128407],"type":1,"volume":0.046019658028041824},{"fixed":false,"mass":0.030272502736832227,"nu":0,"particle_id":49,"point":[-1.980513380690766,0.282215434506385,-0.20537402231552],"type":1,"volume":0.030272502736832227},{"fixed":false,"mass":0.029414348603175062,"nu":0,"particle_id":50,"point":[-2.02514794527919,0.2228317835278485,0.2286519065384029],"type":1,"volume":0.029414348603175062},{"fixed":false,"mass":0.03637849075256033,"nu":0,"particle_id":51,"point":[-1.751503241107395,0.3027956943796303,0.03590712555120758],"type":1,"volume":0.03637849075256033},{"fixed":false,"mass":0.052180746822492484,"nu":0,"particle_id":52,"point":[-2.131743152860462,0.4856842477720718,0.05101062130692252],"type":1,"volume":0.052180746822492484},{"fixed":false,"mass":0.062000633657663576,"nu":0,"particle_id":53,"point":[3.794757863241868,-0.004136862470872707,-0.511249042299535],"type":1,"volume":0.062000633657663576},{"fixed":false,"mass":0.06719113976633666,"nu":0,"particle_id":54,"point":[3.38744552538545,0.2444411091196344,-0.4819660547089512],"type":1,"volume":0.06719113976633666},{"fixed":false,"mass":0.03967670063058805,"nu":0,"particle_id":55,"point":[3.714728074421184,0.3975219399712127,-0.564785539589304],"type":1,"volume":0.03967670063058805},{"fixed":false,"mass":0.02938817294318692,"nu":0,"particle_id":56,"point":[3.586693017596381,0.06679671577746861,-0.9934210977234275],"type":1,"volume":0.02938817294318692},{"fixed":false,"mass":0.020962736219560234,"nu":0,"particle_id":57,"point":[-2.886888848162905,0.3392251215474296,-0.937062466973001],"type":1,"volume":0.020962736219560234},{"fixed":false,"mass":0.05603944588112993,"nu":0,"particle_id":58,"point":[-3.001088910261564,0.4178438313858495,-0.381191636526935],"type":1,"volume":0.05603944588112993},{"fixed":false,"mass":0.056497647817983665,"nu":0,"particle_id":59,"point":[-2.948224730042449,0.0005444167515062676,-0.5316653149372895],"type":1,"volume":0.056497647817983665},{"fixed":false,"mass":0.059080764597205994,"nu":0,"particle_id":60,"point":[-2.632537050480965,0.2637141143860336,-0.526336623665504],"type":1,"volume":0.059080764597205994},{"fixed":false,"mass":0.024735616692548017,"nu":0,"particle_id":61,"point":[-4.134808487816516,0.6860716192372633,-0.7243698924599702],"type":1,"volume":0.024735616692548017},{"fixed":false,"mass":0.021291662689371063,"nu":0,"particle_id":62,"point":[-3.772261540250631,0.5389652345127409,-0.840345168916909],"type":1,"volume":0.021291662689371063},{"fixed":false,"mass":0.04232616277561355,"nu":0,"particle_id":63,"point":[-4.165527657125383,0.2810700091373977,-0.5899010033265667],"type":1,"volume":0.04232616277561355},{"fixed":false,"mass":0.01778072113255871,"nu":0,"particle_id":64,"point":[-3.994203897035045,0.295950675022332,-0.9501896268113327],"type":1,"volume":0.01778072113255871},{"fixed":false,"mass":0.0152911903149972,"nu":0,"particle_id":65,"point":[-4.163450245999107,-0.002851585926546848,-0.9997191433003008],"type":1,"volume":0.0152911903149972},{"fixed":false,"mass":0.009773087941473281,"nu":0,"particle_id":66,"point":[3.875136169143151,-0.914943533056152,0.3994015114734688],"type":1,"volume":0.009773087941473281},{"fixed":false,"mass":0.007935437244414182,"nu":0,"particle_id":67,"point":[3.711213379384667,-0.8317362176760836,0.5550714494478339],"type":1,"volume":0.007935437244414182},{"fixed":false,"mass":0.06124018713388065,"nu":0,"particle_id":68,"point":[3.765406986819124,-0.5160342745431523,0.1366790220410407],"type":1,"volume":0.06124018713388065},{"fixed":false,"mass":0.0553195611313843,"nu":0,"particle_id":69,"point":[-2.452085663670125,0.1723458187824141,0.3359880020836931],"type":1,"volume":0.0553195611313843},{"fixed":false,"mass":0.06695790114868191,"nu":0,"particle_id":70,"point":[-2.657001546581177,-0.2401012859342282,0.4922530147492091],"type":1,"volume":0.06695790114868191},{"fixed":false,"mass":0.038979519934159525,"nu":0,"particle_id":71,"point":[-2.666235304960422,0.110374522219687,0.6483957395881291],"type":1,"volume":0.038979519934159525},{"fixed":false,"mass":0.03371657605498231,"nu":0,"particle_id":72,"point":[-2.877494598898519,-0.04924260156833288,0.3165377806484523],"type":1,"volume":0.03371657605498231},{"fixed":false,"mass":0.015189372697222382,"nu":0,"particle_id":73,"point":[3.942437038659111,0.9950058980689935,0.05070596783859541],"type":1,"volume":0.015189372697222382},{"fixed":false,"mass":0.04741909727899588,"nu":0,"particle_id":74,"point":[3.835234840371672,0.5880263815598717,0.3658945715316854],"type":1,"volume":0.04741909727899588},{"fixed":false,"mass":0.055426982920167046,"nu":0,"particle_id":75,"point":[3.608208811814772,0.5904886110966465,0.0734924615659597],"type":1,"volume":0.055426982920167046},{"fixed":false,"mass":0.07164473328071158,"nu":0,"particle_id":76,"point":[4.133811929341112,0.6281570694088763,0.02135220424911416],"type":1,"volume":0.07164473328071158},{"fixed":false,"mass":0.0266250694971627,"nu":0,"particle_id":77,"point":[-3.171978648913057,-0.1020033080336953,0.9899535510446882],"type":1,"volume":0.0266250694971627},{"fixed":false,"mass":0.04350291982245184,"nu":0,"particle_id":78,"point":[-3.221795091019529,0.125143559246671,0.6588714069930013],"type":1,"volume":0.04350291982245184},{"fixed":false,"mass":0.029893664048290625,"nu":0,"particle_id":79,"point":[-3.031138812059015,0.2688050125016094,0.9584241735113179],"type":1,"volume":0.029893664048290625},{"fixed":false,"mass":0.02923560789763644,"nu":0,"particle_id":80,"point":[-2.948015794283009,-0.06841706834718703,0.7039474490094711],"type":1,"volume":0.02923560789763644},{"fixed":false,"mass":0.020324919338227568,"nu":0,"particle_id":81,"point":[4.470227610638783,0.07446050698183375,0.9926662801726733],"type":1,"volume":0.020324919338227568},{"fixed":false,"mass":0.06552765076101777,"nu":0,"particle_id":82,"point":[4.641835345585677,-0.1910457981121732,0.5769069859138221],"type":1,"volume":0.06552765076101777},{"fixed":false,"mass":0.028944193284204184,"nu":0,"particle_id":83,"point":[4.766424746303289,0.1739255652142404,0.6764622457309343],"type":1,"volume":0.028944193284204184},{"fixed":false,"mass":0.008998692640504338,"nu":0,"particle_id":84,"point":[4.66912773738998,-0.01095229350137986,0.99892129324307],"type":1,"volume":0.008998692640504338},{"fixed":false,"mass":0.01887334696847653,"nu":0,"particle_id":85,"point":[-3.473494931985415,0.8551027956553141,0.5113556568148803],"type":1,"volume":0.01887334696847653},{"fixed":false,"mass":0.012066245768636217,"nu":0,"particle_id":86,"point":[-3.158471419156117,0.8424614256312881,0.5350059966745715],"type":1,"volume":0.012066245768636217},{"fixed":false,"mass":0.045777473332350764,"nu":0,"particle_id":87,"point":[-3.244036160779,0.4966376885717967,0.4005412544482952],"type":1,"volume":0.045777473332350764},{"fixed":false,"mass":0.022385839573594832,"nu":0,"particle_id":88,"point":[-3.358524527244523,0.9818977337158312,0.1837953939850322],"type":1,"volume":0.022385839573594832},{"fixed":false,"mass":0.02492138190271746,"nu":0,"particle_id":89,"point":[-2.429314665521927,-0.7847625600294974,-0.6124829408841327],"type":1,"volume":0.02492138190271746},{"fixed":false,"mass":0.015244736416341881,"nu":0,"particle_id":90,"point":[-2.299630135667146,-0.3964613725420245,-0.9165150700562513],"type":1,"volume":0.015244736416341881},{"fixed":false,"mass":0.01174199713923391,"nu":0,"particle_id":91,"point":[-2.183433358912889,-0.727429130642447,-0.6823439267263032],"type":1,"volume":0.01174199713923391},{"fixed":false,"mass":0.01797165228028419,"nu":0,"particle_id":92,"point":[-1.248285031511733,0.9931103936369955,0.06995134730713878],"type":1,"volume":0.01797165228028419},{"fixed":false,"mass":0.011207159460904087,"nu":0,"particle_id":93,"point":[-0.8828673024779388,0.9901786573787905,-0.0997177650682256],"type":1,"volume":0.011207159460904087},{"fixed":false,"mass":0.02452171711879411,"nu":0,"particle_id":94,"point":[-0.8636269119618498,0.9477091808074602,0.3041276096582257],"type":1,"volume":0.02452171711879411},{"fixed":false,"mass":0.012162340458130276,"nu":0,"particle_id":95,"point":[4.625131757323569,-0.7309668637931728,-0.678033186409555],"type":1,"volume":0.012162340458130276},{"fixed":false,"mass":0.010331519878261888,"nu":0,"particle_id":96,"point":[5,-0.8255475727255929,-0.5627862591227902],"type":2,"volume":0.010331519878261888},{"fixed":false,"mass":0.04922215799184319,"nu":0,"particle_id":97,"point":[4.731443049693974,-0.5082603891272319,-0.4240549369798206],"type":1,"volume":0.04922215799184319},{"fixed":false,"mass":0.012845635539748339,"nu":0,"particle_id":98,"point":[4.639413286153015,-0.8930004658127295,-0.4404541028369581],"type":1,"volume":0.012845635539748339},{"fixed":false,"mass":0.0415740283488638,"nu":0,"particle_id":99,"point":[2.726271162374811,0.4194926846088941,-0.2264019549683927],"type":1,"volume":0.0415740283488638},{"fixed":false,"mass":0.04434636188419469,"nu":0,"particle_id":100,"point":[2.482100586403666,0.2023428111795482,-0.2587750445329458],"type":1,"volume":0.04434636188419469},{"fixed":false,"mass":0.03350065504483024,"nu":0,"particle_id":101,"point":[2.630417818503024,0.3823542062172355,-0.5708564806077383],"type":1,"volume":0.03350065504483024},{"fixed":false,"mass":0.048198236203256764,"nu":0,"particle_id":102,"point":[2.613208399173119,0.04821555445505243,-0.5173806995248806],"type":1,"volume":0.048198236203256764},{"fixed":false,"mass":0.01563566998582991,"nu":0,"particle_id":103,"point":[2.359410257644354,-0.2218500007179617,-0.9726678206146318],"type":1,"volume":0.01563566998582991},{"fixed":false,"mass":0.04245496335124077,"nu":0,"particle_id":104,"point":[2.485021502642345,-0.2684493881879212,-0.6065524476145281],"type":1,"volume":0.04245496335124077},{"fixed":false,"mass":0.020608491795495964,"nu":0,"particle_id":105,"point":[2.07136768782369,-0.2542339570198517,-0.9628442548683678],"type":1,"volume":0.020608491795495964},{"fixed":false,"mass":0.042622257385584554,"nu":0,"particle_id":106,"point":[2.903495434461601,-0.611315087520766,-0.06045751580979139],"type":1,"volume":0.042622257385584554},{"fixed":false,"mass":0.026812109857870775,"nu":0,"particle_id":107,"point":[3.209619685308639,-0.7493044711448648,0.07383366403101324],"type":1,"volume":0.026812109857870775},{"fixed":false,"mass":0.018427730125859222,"nu":0,"particle_id":108,"point":[3.004478551053779,0.9967494973367,0.03300290738586065],"type":1,"volume":0.018427730125859222},{"fixed":false,"mass":0.054031996088323084,"nu":0,"particle_id":109,"point":[3.031195686285311,0.6226924837950327,-0.267716357753779],"type":1,"volume":0.054031996088323084},{"fixed":false,"mass":0.0273730865105633,"nu":0,"particle_id":110,"point":[2.865232750361471,0.9509856974164264,-0.2933263819342162],"type":1,"volume":0.0273730865105633},{"fixed":false,"mass":0.01738075977794174,"nu":0,"particle_id":111,"point":[3.303494366453592,0.9614278671480658,-0.2589031615862529],"type":1,"volume":0.01738075977794174},{"fixed":false,"mass":0.04175792878178565,"nu":0,"particle_id":112,"point":[-0.9179192611273244,-0.5285992971443779,0.4012563113680896],"type":1,"volume":0.04175792878178565},{"fixed":false,"mass":0.033492192110906226,"nu":0,"particle_id":113,"point":[-1.16698042413296,-0.2609363612989061,0.6697467614891082],"type":1,"volume":0.033492192110906226},{"fixed":false,"mass":0.0497308649233907,"nu":0,"particle_id":114,"point":[-1.26445286206162,-0.4463301434603677,0.3791146994252123],"type":1,"volume":0.0497308649233907},{"fixed":false,"mass":0.013800538609696733,"nu":0,"particle_id":115,"point":[-1.028532793874813,-0.7162333660987635,0.6959860052944342],"type":1,"volume":0.013800538609696733},{"fixed":false,"mass":0.05104898920452672,"nu":0,"particle_id":116,"point":[-0.8682995986733436,0.3724337213499915,-0.3439806528218857],"type":1,"volume":0.05104898920452672},{"fixed":false,"mass":0.015338087683882836,"nu":0,"particle_id":117,"point":[-1.01116452364028,0.7037806021603097,-0.70983650576788],"type":1,"volume":0.015338087683882836},{"fixed":false,"mass":0.03814371303425343,"nu":0,"particle_id":118,"point":[-1.142573192933489,0.5981281595684412,-0.3616162319985682],"type":1,"volume":0.03814371303425343},{"fixed":false,"mass":0.015473931704047993,"nu":0,"particle_id":119,"point":[-0.9068978359538125,0.8595001219446659,-0.503128837963801],"type":1,"volume":0.015473931704047993},{"fixed":false,"mass":0.05951023214044787,"nu":0,"particle_id":120,"point":[1.644430629452296,-0.2422453764238503,-0.3770072205984468],"type":1,"volume":0.05951023214044787},{"fixed":false,"mass":0.05186599901226912,"nu":0,"particle_id":121,"point":[1.553509101920363,-0.2717274887044852,-0.0271684343837898],"type":1,"volume":0.05186599901226912},{"fixed":false,"mass":0.048571334739899365,"nu":0,"particle_id":122,"point":[1.877994461028244,-0.3423147572615952,0.1186046244977769],"type":1,"volume":0.048571334739899365},{"fixed":false,"mass":0.019107503931947913,"nu":0,"particle_id":123,"point":[-4.23382319833847,-0.3678757040352918,0.9283714077918894],"type":1,"volume":0.019107503931947913},{"fixed":false,"mass":0.042791074496450025,"nu":0,"particle_id":124,"point":[-4.286868845923317,-0.006749008237184329,0.6873116441004872],"type":1,"volume":0.042791074496450025},{"fixed":false,"mass":0.017457686213554268,"nu":0,"particle_id":125,"point":[-4.469528185181522,-0.1206298150342931,0.9881190002305573],"type":1,"volume":0.017457686213554268},{"fixed":false,"mass":0.009187687956726073,"nu":0,"particle_id":126,"point":[-4.121842564707817,-0.1093257466001983,0.9892323537942768],"type":1,"volume":0.009187687956726073},{"fixed":false,"mass":0.01967202309705833,"nu":0,"particle_id":127,"point":[-1.497297833742455,0.7730425430140191,0.6267638229374444],"type":1,"volume":0.01967202309705833},{"fixed":false,"mass":0.033399541320003646,"nu":0,"particle_id":128,"point":[-0.9989351068213506,0.7197641802245641,0.6916836958339504],"type":1,"volume":0.033399541320003646},{"fixed":false,"mass":0.053998447117040674,"nu":0,"particle_id":129,"point":[-1.422027367440409,0.5498804681824593,0.3116864555503576],"type":1,"volume":0.053998447117040674},{"fixed":false,"mass":0.025076391600170982,"nu":0,"particle_id":130,"point":[-1.234654648671424,0.8838788673250885,0.4575194133125117],"type":1,"volume":0.025076391600170982},{"fixed":false,"mass":0.05325489740221358,"nu":0,"particle_id":131,"point":[-2.222809708544816,-0.4682152286517877,-0.3009835829689027],"type":1,"volume":0.05325489740221358},{"fixed":false,"mass":0.017176132138938188,"nu":0,"particle_id":132,"point":[-2.000976054972893,-0.842963877563046,-0.5340659752270032],"type":1,"volume":0.017176132138938188},{"fixed":false,"mass":0.03276955556881834,"nu":0,"particle_id":133,"point":[-2.127882474572919,-0.7152992946383896,-0.0705832773266464],"type":1,"volume":0.03276955556881834},{"fixed":false,"mass":0.017000344905002927,"nu":0,"particle_id":134,"point":[-4.581174487303853,0.1658744873198582,0.9836627889627169],"type":1,"volume":0.017000344905002927},{"fixed":false,"mass":0.016815502398507085,"nu":0,"particle_id":135,"point":[-4.08394799071251,0.1763527752889206,0.9826307676758634],"type":1,"volume":0.016815502398507085},{"fixed":false,"mass":0.07122160409049327,"nu":0,"particle_id":136,"point":[2.584406117911328,0.4282841933368184,0.2885918838631453],"type":1,"volume":0.07122160409049327},{"fixed":false,"mass":0.04352441592228286,"nu":0,"particle_id":137,"point":[2.669674616520518,-0.06333015432216049,0.2387578156964944],"type":1,"volume":0.04352441592228286},{"fixed":false,"mass":0.03508065828659006,"nu":0,"particle_id":138,"point":[2.439190042674461,0.003483285209622544,-0.001025303900104912],"type":1,"volume":0.03508065828659006},{"fixed":false,"mass":0.04507748622520616,"nu":0,"particle_id":139,"point":[2.836972291389031,0.09057463102152422,-0.01305148508178539],"type":1,"volume":0.04507748622520616},{"fixed":false,"mass":0.020478523228076417,"nu":0,"particle_id":140,"point":[3.768427928956693,-0.70598721601205,-0.7080255845802081],"type":1,"volume":0.020478523228076417},{"fixed":false,"mass":0.049035754952812406,"nu":0,"particle_id":141,"point":[3.901214334166843,-0.3774401560656327,-0.5416524397414633],"type":1,"volume":0.049035754952812406},{"fixed":false,"mass":0.011367353919784459,"nu":0,"particle_id":142,"point":[4.037616390941182,-0.6989597369872793,-0.7137928875688306],"type":1,"volume":0.011367353919784459},{"fixed":false,"mass":0.014174200421622775,"nu":0,"particle_id":143,"point":[3.712953920413026,-0.5003755566962815,-0.8609717814425597],"type":1,"volume":0.014174200421622775},{"fixed":false,"mass":0.02454320507947816,"nu":0,"particle_id":144,"point":[3.755971535920696,0.7566817200312581,-0.6466995434234597],"type":1,"volume":0.02454320507947816},{"fixed":false,"mass":0.043541275909343195,"nu":0,"particle_id":145,"point":[3.8569831839802,0.4423401131255426,-0.2254310200778576],"type":1,"volume":0.043541275909343195},{"fixed":false,"mass":0.06077121442951237,"nu":0,"particle_id":146,"point":[4.166917116178171,0.4526310252409118,-0.4630479163559781],"type":1,"volume":0.06077121442951237},{"fixed":false,"mass":0.03376643982001596,"nu":0,"particle_id":147,"point":[-2.291229868911083,0.5166338518804474,0.400559509822827],"type":1,"volume":0.03376643982001596},{"fixed":false,"mass":0.05813814043635522,"nu":0,"particle_id":148,"point":[-2.089019738922628,0.1602425315893123,0.5511629326689705],"type":1,"volume":0.05813814043635522},{"fixed":false,"mass":0.031490956750285404,"nu":0,"particle_id":149,"point":[-1.982771627538392,0.5950715980010555,0.4643996093569837],"type":1,"volume":0.031490956750285404},{"fixed":false,"mass":0.040863336256105526,"nu":0,"particle_id":150,"point":[0.2804890241801438,-0.1807348725153986,-0.2469684450307683],"type":1,"volume":0.040863336256105526},{"fixed":false,"mass":0.029248526059206695,"nu":0,"particle_id":151,"point":[0.1464929224144694,0.001887809785750094,0.002374694646108066],"type":1,"volume":0.029248526059206695},{"fixed":false,"mass":0.031870734686458735,"nu":0,"particle_id":152,"point":[-0.02719704938420842,-0.2708609224709452,-0.1219719952587592],"type":1,"volume":0.031870734686458735},{"fixed":false,"mass":0.035366386188934264,"nu":0,"particle_id":153,"point":[0.3580969970421717,-0.2519687569508218,0.09900697936266609],"type":1,"volume":0.035366386188934264},{"fixed":false,"mass":0.03164152165882779,"nu":0,"particle_id":154,"point":[-0.09706948033881332,-0.1114279694290356,0.2495328926244624],"type":1,"volume":0.03164152165882779},{"fixed":false,"mass":0.06220567887781521,"nu":0,"particle_id":155,"point":[-0.06142881306223297,-0.433705501208198,0.2244594002694189],"type":1,"volume":0.06220567887781521},{"fixed":false,"mass":0.05581128152118555,"nu":0,"particle_id":156,"point":[-0.6113005999645312,-0.1565625978970077,0.1059926925979835],"type":1,"volume":0.05581128152118555},{"fixed":false,"mass":0.0347185406990124,"nu":0,"particle_id":157,"point":[-0.263994416510661,-0.03939980615759548,-0.02011456991178084],"type":1,"volume":0.0347185406990124},{"fixed":false,"mass":0.06096333072034879,"nu":0,"particle_id":158,"point":[4.316342829477622,0.4668793652655274,0.4988115372624441],"type":1,"volume":0.06096333072034879},{"fixed":false,"mass":0.018411999350241032,"nu":0,"particle_id":159,"point":[4.358631440599966,0.3224217010924196,0.9421597288412875],"type":1,"volume":0.018411999350241032},{"fixed":false,"mass":0.012778122939765511,"nu":0,"particle_id":160,"point":[4.577394873011919,0.6205798941161924,0.7781175622416145],"type":1,"volume":0.012778122939765511},{"fixed":false,"mass":0.019258254157291224,"nu":0,"particle_id":161,"point":[4.125111369461218,0.6568414038131144,0.7483585103099228],"type":1,"volume":0.019258254157291224},{"fixed":false,"mass":0.017317057508588984,"nu":0,"particle_id":162,"point":[2.637986448701776,0.2932124143793697,-0.9510202690962278],"type":1,"volume":0.017317057508588984},{"fixed":false,"mass":0.05072312281229734,"nu":0,"particle_id":163,"point":[2.954745868257494,0.2865624473144734,-0.549887051757129],"type":1,"volume":0.05072312281229734},{"fixed":false,"mass":0.011259576563896001,"nu":0,"particle_id":164,"point":[2.788659094336903,0.5216073083549893,-0.8496231737452388],"type":1,"volume":0.011259576563896001},{"fixed":false,"mass":0.020084509525193705,"nu":0,"particle_id":165,"point":[1.622883894408121,-0.9623097974996764,-0.2559958268459387],"type":1,"volume":0.020084509525193705},{"fixed":false,"mass":0.00860322199108107,"nu":0,"particle_id":166,"point":[1.695184023569132,-0.9981469377263299,-0.01881445700342388],"type":1,"volume":0.00860322199108107},{"fixed":false,"mass":0.0441936931984438,"nu":0,"particle_id":167,"point":[1.669020333349457,-0.6364484718535957,0.04507227898337507],"type":1,"volume":0.0441936931984438},{"fixed":false,"mass":0.018308272626710035,"nu":0,"particle_id":168,"point":[1.445973895768965,-0.9993236560842135,0.006867035017603131],"type":1,"volume":0.018308272626710035},{"fixed":false,"mass":0.011126473967407744,"nu":0,"particle_id":169,"point":[5,-0.07432012267281404,0.992680106820278],"type":2,"volume":0.011126473967407744},{"fixed":false,"mass":0.06548699959659099,"nu":0,"particle_id":170,"point":[1.430549334342659,0.4200101697179852,-0.3345195065694664],"type":1,"volume":0.06548699959659099},{"fixed":false,"mass":0.03243712803820598,"nu":0,"particle_id":171,"point":[1.251420724789132,0.3438361015556008,-0.6014364019936695],"type":1,"volume":0.03243712803820598},{"fixed":false,"mass":0.045990435353122104,"nu":0,"particle_id":172,"point":[1.230926238145538,-0.08206898078811309,-0.3249167633466765],"type":1,"volume":0.045990435353122104},{"fixed":false,"mass":0.04500040396672952,"nu":0,"particle_id":173,"point":[1.025235287984389,0.1749554597692072,-0.4298157345577643],"type":1,"volume":0.04500040396672952},{"fixed":false,"mass":0.030215402254849286,"nu":0,"particle_id":174,"point":[1.043043084670435,-0.6187282275555388,-0.7796371857156297],"type":1,"volume":0.030215402254849286},{"fixed":false,"mass":0.041252884712704954,"nu":0,"particle_id":175,"point":[1.041722161137601,-0.1750643779343342,-0.6329610106790413],"type":1,"volume":0.041252884712704954},{"fixed":false,"mass":0.023478397021505684,"nu":0,"particle_id":176,"point":[1.277311137273452,-0.16744637283478,-0.9835079717524355],"type":1,"volume":0.023478397021505684},{"fixed":false,"mass":0.019047552409874487,"nu":0,"particle_id":177,"point":[0.8228275448557336,-0.3097870455998258,-0.9459924096834877],"type":1,"volume":0.019047552409874487},{"fixed":false,"mass":0.05353149841073262,"nu":0,"particle_id":178,"point":[-2.611153228887777,-0.4293544633449046,-0.5039926659942123],"type":1,"volume":0.05353149841073262},{"fixed":false,"mass":0.05160049967370638,"nu":0,"particle_id":179,"point":[-0.887673808786921,-0.3444202559562685,-0.4338308153953075],"type":1,"volume":0.05160049967370638},{"fixed":false,"mass":0.054387177448447364,"nu":0,"particle_id":180,"point":[-0.6530675834219872,-0.08278083959971977,-0.2586588510580682],"type":1,"volume":0.054387177448447364},{"fixed":false,"mass":0.05711715299782085,"nu":0,"particle_id":181,"point":[-0.8721552983896601,0.04090107388217843,-0.6047349965454134],"type":1,"volume":0.05711715299782085},{"fixed":false,"mass":0.043907051297024456,"nu":0,"particle_id":182,"point":[-1.140498698538972,-0.2094897876607019,-0.209791237887078],"type":1,"volume":0.043907051297024456},{"fixed":false,"mass":0.012388147453784384,"nu":0,"particle_id":183,"point":[-3.779967116720712,-0.8171733690047049,0.5729902558806841],"type":1,"volume":0.012388147453784384},{"fixed":false,"mass":0.01933593070719012,"nu":0,"particle_id":184,"point":[-3.741976998362208,-0.6349214103091385,0.7663477840737378],"type":1,"volume":0.01933593070719012},{"fixed":false,"mass":0.0383827906843849,"nu":0,"particle_id":185,"point":[-3.774762518072331,-0.6368660553408199,0.294612446407196],"type":1,"volume":0.0383827906843849},{"fixed":false,"mass":0.0529803305091851,"nu":0,"particle_id":186,"point":[-3.765298815547263,-0.3454276660684436,0.5809187025032959],"type":1,"volume":0.0529803305091851},{"fixed":false,"mass":0.010761422143047223,"nu":0,"particle_id":187,"point":[-1.355220484814595,0.9818851458304712,-0.1839232009299126],"type":1,"volume":0.010761422143047223},{"fixed":false,"mass":0.038432233012205747,"nu":0,"particle_id":188,"point":[-1.448533113431858,0.7231388867266131,0.02066803818219076],"type":1,"volume":0.038432233012205747},{"fixed":false,"mass":0.060107954321520884,"nu":0,"particle_id":189,"point":[1.976080069676443,-0.4980590251520869,-0.272009537878146],"type":1,"volume":0.060107954321520884},{"fixed":false,"mass":0.052083910525175185,"nu":0,"particle_id":190,"point":[2.314304501904654,-0.5276462815449436,0.03924412561754409],"type":1,"volume":0.052083910525175185},{"fixed":false,"mass":0.0366237249091505,"nu":0,"particle_id":191,"point":[2.006865962016344,-0.6645890904191989,0.01950606374945546],"type":1,"volume":0.0366237249091505},{"fixed":false,"mass":0.037950981790897474,"nu":0,"particle_id":192,"point":[4.718459257846357,0.6138550570378866,0.3324436665725002],"type":1,"volume":0.037950981790897474},{"fixed":false,"mass":0.012568012567323122,"nu":0,"particle_id":193,"point":[5,0.7307949394943561,0.6782426767737967],"type":2,"volume":0.012568012567323122},{"fixed":false,"mass":0.015584940717585496,"nu":0,"particle_id":194,"point":[5,0.5655812075058759,0.1738274711702137],"type":2,"volume":0.015584940717585496},{"fixed":false,"mass":0.007139636409697404,"nu":0,"particle_id":195,"point":[5,0.8974766981659316,0.4320796611235228],"type":2,"volume":0.007139636409697404},{"fixed":false,"mass":0.05130388272332369,"nu":0,"particle_id":196,"point":[-0.2134640623790376,0.2210589010719869,0.2014659959138561],"type":1,"volume":0.05130388272332369},{"fixed":false,"mass":0.04118520515664656,"nu":0,"particle_id":197,"point":[-0.3900603800425489,-0.04366305435182782,0.3733310898966431],"type":1,"volume":0.04118520515664656},{"fixed":false,"mass":0.060971969387388386,"nu":0,"particle_id":198,"point":[-0.7078602687043036,0.2200208281606869,0.5286331338903687],"type":1,"volume":0.060971969387388386},{"fixed":false,"mass":0.026784986748697427,"nu":0,"particle_id":199,"point":[2.546725285247547,0.9976720016701037,-0.02363656370550522],"type":1,"volume":0.026784986748697427},{"fixed":false,"mass":0.01841967890201672,"nu":0,"particle_id":200,"point":[2.241944656227243,0.9910743258764679,-0.09062389020049263],"type":1,"volume":0.01841967890201672},{"fixed":false,"mass":0.05378750652672684,"nu":0,"particle_id":201,"point":[2.622861250459029,0.04993176822089493,0.555085754055386],"type":1,"volume":0.05378750652672684},{"fixed":false,"mass":0.052632587234752615,"nu":0,"particle_id":202,"point":[2.31475823389354,0.2965986146807879,0.5451454618673544],"type":1,"volume":0.052632587234752615},{"fixed":false,"mass":0.04503448182416673,"nu":0,"particle_id":203,"point":[2.815098962522789,0.3659362227269857,0.5945549112474449],"type":1,"volume":0.04503448182416673},{"fixed":false,"mass":0.014791410382874026,"nu":0,"particle_id":204,"point":[0.1703611195455475,-0.6525684058432695,-0.7518652691170287],"type":1,"volume":0.014791410382874026},{"fixed":false,"mass":0.04980822863146771,"nu":0,"particle_id":205,"point":[0.3539926782200524,-0.411265318133516,-0.5248426881142152],"type":1,"volume":0.04980822863146771},{"fixed":false,"mass":0.02142049848705028,"nu":0,"particle_id":206,"point":[0.220684816381087,-0.9211462254393796,-0.3877970902256412],"type":1,"volume":0.02142049848705028},{"fixed":false,"mass":0.01670417280933862,"nu":0,"particle_id":207,"point":[0.5616357209188636,-0.842483800929847,-0.5349641354352934],"type":1,"volume":0.01670417280933862},{"fixed":false,"mass":0.0215612287944107,"nu":0,"particle_id":208,"point":[2.16817532706386,-0.9637735709995014,-0.251170412299064],"type":1,"volume":0.0215612287944107},{"fixed":false,"mass":0.025125617150472873,"nu":0,"particle_id":209,"point":[2.396758771419484,-0.9835269635599491,0.1672535457771258],"type":1,"volume":0.025125617150472873},{"fixed":false,"mass":0.006067522069155262,"nu":0,"particle_id":210,"point":[2.032904639564197,-0.9970294301939139,-0.03016070138947838],"type":1,"volume":0.006067522069155262},{"fixed":false,"mass":0.012640512265626618,"nu":0,"particle_id":211,"point":[1.945895670362404,-0.971022653565871,0.2272733896576272],"type":1,"volume":0.012640512265626618},{"fixed":false,"mass":0.007420863877725041,"nu":0,"particle_id":212,"point":[1.672920879932996,-0.9704429429707955,0.2291844393786319],"type":1,"volume":0.007420863877725041},{"fixed":false,"mass":0.040795126287506506,"nu":0,"particle_id":213,"point":[-1.923737019039039,-0.000344896793819327,0.000795864579972605],"type":1,"volume":0.040795126287506506},{"fixed":false,"mass":0.06602767342440348,"nu":0,"particle_id":214,"point":[-1.791359981000157,0.2192192983831051,-0.472466256690376],"type":1,"volume":0.06602767342440348},{"fixed":false,"mass":0.050987091718431736,"nu":0,"particle_id":215,"point":[-2.118928599763412,-0.1321005404325298,-0.2632643652326372],"type":1,"volume":0.050987091718431736},{"fixed":false,"mass":0.049994943224380174,"nu":0,"particle_id":216,"point":[-4.244471378180799,0.1057116680236929,-0.2667330604326831],"type":1,"volume":0.049994943224380174},{"fixed":false,"mass":0.04297700513456141,"nu":0,"particle_id":217,"point":[-4.725438317961745,-0.5773980462217783,0.2950708099068466],"type":1,"volume":0.04297700513456141},{"fixed":false,"mass":0.014492263353722452,"nu":0,"particle_id":218,"point":[-4.628484382721567,-0.8491992531451185,0.522400408014861],"type":1,"volume":0.014492263353722452},{"fixed":false,"mass":0.012382845811234377,"nu":0,"particle_id":219,"point":[-4.66358723657406,-0.9644527878247422,0.248931334498168],"type":1,"volume":0.012382845811234377},{"fixed":false,"mass":0.016341496255111186,"nu":0,"particle_id":220,"point":[-4.401440881428885,-0.9644527878247422,0.2489313344981679],"type":1,"volume":0.016341496255111186},{"fixed":false,"mass":0.03955041570191596,"nu":0,"particle_id":221,"point":[-0.3901535293248091,0.1842105521367453,-0.3438313837875795],"type":1,"volume":0.03955041570191596},{"fixed":false,"mass":0.03466301497481085,"nu":0,"particle_id":222,"point":[-3.623269714118908,-0.3430659956403732,0.2669813898696893],"type":1,"volume":0.03466301497481085},{"fixed":false,"mass":0.05247254154781742,"nu":0,"particle_id":223,"point":[-3.656227582318592,-0.6099089907546833,-0.05906573067550146],"type":1,"volume":0.05247254154781742},{"fixed":false,"mass":0.060702493319177195,"nu":0,"particle_id":224,"point":[-3.321290032452492,-0.5229086454167138,0.387571731807778],"type":1,"volume":0.060702493319177195},{"fixed":false,"mass":0.03595135821568968,"nu":0,"particle_id":225,"point":[-2.650617719427015,0.5520397342339017,0.2657814980772468],"type":1,"volume":0.03595135821568968},{"fixed":false,"mass":0.02900406132160918,"nu":0,"particle_id":226,"point":[-2.933667413964816,0.6777611645461779,0.7311901063670876],"type":1,"volume":0.02900406132160918},{"fixed":false,"mass":0.01936680536307532,"nu":0,"particle_id":227,"point":[-2.523828202905612,0.7900189660264879,0.6060779916448782],"type":1,"volume":0.01936680536307532},{"fixed":false,"mass":0.020907363007720173,"nu":0,"particle_id":228,"point":[-2.85462350112455,0.8836524359803348,0.4579430365628506],"type":1,"volume":0.020907363007720173},{"fixed":false,"mass":0.015089619995901228,"nu":0,"particle_id":229,"point":[3.359579492739011,0.9989881649458106,-0.01027333370933159],"type":1,"volume":0.015089619995901228},{"fixed":false,"mass":0.04446024279119151,"nu":0,"particle_id":230,"point":[3.281346229988637,0.697286415061715,0.1575591175424584],"type":1,"volume":0.04446024279119151},{"fixed":false,"mass":0.014662313925626521,"nu":0,"particle_id":231,"point":[3.462530543582908,0.932582972035623,0.3539920373551405],"type":1,"volume":0.014662313925626521},{"fixed":false,"mass":0.014161336678009558,"nu":0,"particle_id":232,"point":[-1.623360153764553,-0.7420949084017059,-0.6644736248211564],"type":1,"volume":0.014161336678009558},{"fixed":false,"mass":0.017913092307185675,"nu":0,"particle_id":233,"point":[-1.479097255507918,-0.8717162118910101,-0.4802741411676075],"type":1,"volume":0.017913092307185675},{"fixed":false,"mass":0.012256178460108182,"nu":0,"particle_id":234,"point":[3.500380593621476,0.3239639023891315,-0.9416919071924755],"type":1,"volume":0.012256178460108182},{"fixed":false,"mass":0.013832789815259152,"nu":0,"particle_id":235,"point":[4.631652644816967,0.3646659590504711,0.9293450732882601],"type":1,"volume":0.013832789815259152},{"fixed":false,"mass":0.03861926476871549,"nu":0,"particle_id":236,"point":[4.554935918488046,0.1876211452607776,0.4946977090498405],"type":1,"volume":0.03861926476871549},{"fixed":false,"mass":0.02653039448595846,"nu":0,"particle_id":237,"point":[4.720631935337295,0.4323038046161671,0.5810832969751274],"type":1,"volume":0.02653039448595846},{"fixed":false,"mass":0.01821567544095969,"nu":0,"particle_id":238,"point":[-0.6211792601103627,0.4904260980424199,0.8662898778897307],"type":1,"volume":0.01821567544095969},{"fixed":false,"mass":0.024664833805207873,"nu":0,"particle_id":239,"point":[-0.9868704177975718,0.4172574606372655,0.9053993293851313],"type":1,"volume":0.024664833805207873},{"fixed":false,"mass":0.04518350807306459,"nu":0,"particle_id":240,"point":[-0.27449427764248,-0.4056946332562018,0.5155514033898181],"type":1,"volume":0.04518350807306459},{"fixed":false,"mass":0.013050651800567963,"nu":0,"particle_id":241,"point":[-0.2326689704870231,-0.7565715681208417,0.6468337639146514],"type":1,"volume":0.013050651800567963},{"fixed":false,"mass":0.02039743266602668,"nu":0,"particle_id":242,"point":[-0.4965898320700237,-0.8770694845646898,0.4702588724227248],"type":1,"volume":0.02039743266602668},{"fixed":false,"mass":0.046242392183584606,"nu":0,"particle_id":243,"point":[-0.3264956225904182,-0.6713137375296876,0.1127773888973282],"type":1,"volume":0.046242392183584606},{"fixed":false,"mass":0.03983341045496021,"nu":0,"particle_id":244,"point":[-1.423138983049572,0.3914759023133282,-0.04837945508626592],"type":1,"volume":0.03983341045496021},{"fixed":false,"mass":0.059241148077821854,"nu":0,"particle_id":245,"point":[-1.790502241547888,0.5560338705301527,-0.2031347055771224],"type":1,"volume":0.059241148077821854},{"fixed":false,"mass":0.06513612222917221,"nu":0,"particle_id":246,"point":[-1.421840575445583,0.4013357593315888,-0.4603961787381728],"type":1,"volume":0.06513612222917221},{"fixed":false,"mass":0.042399009052577555,"nu":0,"particle_id":247,"point":[-3.732257578167739,0.6967826845252046,-0.1806601967960424],"type":1,"volume":0.042399009052577555},{"fixed":false,"mass":0.05784585926394923,"nu":0,"particle_id":248,"point":[-3.5719548126761,0.573571802567078,0.1064926930596967],"type":1,"volume":0.05784585926394923},{"fixed":false,"mass":0.019208681182372338,"nu":0,"particle_id":249,"point":[-3.941251784932897,0.9659417848489575,0.244022769134906],"type":1,"volume":0.019208681182372338},{"fixed":false,"mass":0.05779099202540287,"nu":0,"particle_id":250,"point":[-3.991167229799399,0.4600377614269088,0.2208718282152309],"type":1,"volume":0.05779099202540287},{"fixed":false,"mass":0.027246604549729436,"nu":0,"particle_id":251,"point":[2.762286578011245,-0.7376769551758845,0.6698569164027024],"type":1,"volume":0.027246604549729436},{"fixed":false,"mass":0.010735431574733183,"nu":0,"particle_id":252,"point":[3.034092735540215,-0.7612969354802954,0.6410758871274593],"type":1,"volume":0.010735431574733183},{"fixed":false,"mass":0.016561369888202105,"nu":0,"particle_id":253,"point":[2.595660188112221,-0.8649499186531455,0.4929329854512324],"type":1,"volume":0.016561369888202105},{"fixed":false,"mass":0.01662252418821754,"nu":0,"particle_id":254,"point":[3.000738307978109,-0.9680713228748346,0.237002623074472],"type":1,"volume":0.01662252418821754},{"fixed":false,"mass":0.0385992546550043,"nu":0,"particle_id":255,"point":[-2.449315744489684,-0.0713669524833767,-0.3743628516285494],"type":1,"volume":0.0385992546550043},{"fixed":false,"mass":0.03795060692374416,"nu":0,"particle_id":256,"point":[1.551106646202626,0.08702337725439227,-0.2582411552341164],"type":1,"volume":0.03795060692374416},{"fixed":false,"mass":0.03172220774774193,"nu":0,"particle_id":257,"point":[1.313583252689975,-0.001201945660691317,0.0006634337775427435],"type":1,"volume":0.03172220774774193},{"fixed":false,"mass":0.017816547930799505,"nu":0,"particle_id":258,"point":[0.09208802368683108,-0.4091217359178557,-0.909747964846686],"type":1,"volume":0.017816547930799505},{"fixed":false,"mass":0.06008165912143045,"nu":0,"particle_id":259,"point":[0.2716134711824784,-0.006982382941184362,-0.6664299211162991],"type":1,"volume":0.06008165912143045},{"fixed":false,"mass":0.015536101042812698,"nu":0,"particle_id":260,"point":[0.3389758279346176,-0.246927908787645,-0.965060520369883],"type":1,"volume":0.015536101042812698},{"fixed":false,"mass":0.04784749485135373,"nu":0,"particle_id":261,"point":[-2.944818702593216,0.2634161078302794,0.4332942087887567],"type":1,"volume":0.04784749485135373},{"fixed":false,"mass":0.0437238782557406,"nu":0,"particle_id":262,"point":[-3.176326688331394,0.1982386649789024,0.1921049533601179],"type":1,"volume":0.0437238782557406},{"fixed":false,"mass":0.034009036436068896,"nu":0,"particle_id":263,"point":[-2.965965691998243,0.6264614454899238,0.2930695056117866],"type":1,"volume":0.034009036436068896},{"fixed":false,"mass":0.04346040122391015,"nu":0,"particle_id":264,"point":[2.055417967810698,-0.08953325585187866,0.2353308933121659],"type":1,"volume":0.04346040122391015},{"fixed":false,"mass":0.05057708996023517,"nu":0,"particle_id":265,"point":[1.764676645304604,0.154879474044467,0.6286521066553233],"type":1,"volume":0.05057708996023517},{"fixed":false,"mass":0.05246062891460717,"nu":0,"particle_id":266,"point":[2.091516092352272,0.01074983478114028,0.6442918335233909],"type":1,"volume":0.05246062891460717},{"fixed":false,"mass":0.031117675621858926,"nu":0,"particle_id":267,"point":[1.984114038263493,0.2131705042721856,0.3461857230812977],"type":1,"volume":0.031117675621858926},{"fixed":false,"mass":0.05547304614986795,"nu":0,"particle_id":268,"point":[0.7309734088374022,0.3579390469967677,-0.006241363408466163],"type":1,"volume":0.05547304614986795},{"fixed":false,"mass":0.0401365015605301,"nu":0,"particle_id":269,"point":[0.853561061423662,0.6785242834383576,0.183310649289318],"type":1,"volume":0.0401365015605301},{"fixed":false,"mass":0.04575876605048528,"nu":0,"particle_id":270,"point":[1.101590183673197,0.4390743630531485,0.2916818559268473],"type":1,"volume":0.04575876605048528},{"fixed":false,"mass":0.04271755112343119,"nu":0,"particle_id":271,"point":[1.104343149644603,0.2672802091653482,-0.002174111708990928],"type":1,"volume":0.04271755112343119},{"fixed":false,"mass":0.00919851023272194,"nu":0,"particle_id":272,"point":[-3.231236722780848,-0.8758218901060292,0.4725929574861566],"type":1,"volume":0.00919851023272194},{"fixed":false,"mass":0.0168190582496125,"nu":0,"particle_id":273,"point":[-3.466428530448789,-0.9634428730035238,0.2522605774923838],"type":1,"volume":0.0168190582496125},{"fixed":false,"mass":0.02401013675887693,"nu":0,"particle_id":274,"point":[-3.216398791279985,-0.9812936929618865,0.1899283226808908],"type":1,"volume":0.02401013675887693},{"fixed":false,"mass":0.07076483878508204,"nu":0,"particle_id":275,"point":[1.554823780941022,0.4707388199591795,0.1295872958796775],"type":1,"volume":0.07076483878508204},{"fixed":false,"mass":0.053422047586845996,"nu":0,"particle_id":276,"point":[-2.62022273422353,0.4233376160432277,-0.1477681476080798],"type":1,"volume":0.053422047586845996},{"fixed":false,"mass":0.05910514806405214,"nu":0,"particle_id":277,"point":[-2.845451448736572,0.6527111659690945,-0.007787336776908696],"type":1,"volume":0.05910514806405214},{"fixed":false,"mass":0.04000180720949578,"nu":0,"particle_id":278,"point":[-2.381518577149798,0.6982704059567557,0.1263086563368094],"type":1,"volume":0.04000180720949578},{"fixed":false,"mass":0.03910817554952516,"nu":0,"particle_id":279,"point":[-1.773091574405002,0.6721965948523088,0.1549563614052068],"type":1,"volume":0.03910817554952516},{"fixed":false,"mass":0.015325411380426474,"nu":0,"particle_id":280,"point":[-2.034778186200481,0.9104544300482976,0.4078000324881322],"type":1,"volume":0.015325411380426474},{"fixed":false,"mass":0.01637535209867751,"nu":0,"particle_id":281,"point":[-1.792545222838324,0.8594659063449056,0.5031928508485828],"type":1,"volume":0.01637535209867751},{"fixed":false,"mass":0.017656346798931827,"nu":0,"particle_id":282,"point":[0.2350680877926,0.9712696414793123,0.226459179624063],"type":1,"volume":0.017656346798931827},{"fixed":false,"mass":0.030415187250234937,"nu":0,"particle_id":283,"point":[0.1529835688709975,0.7178391426300462,0.04210563548242269],"type":1,"volume":0.030415187250234937},{"fixed":false,"mass":0.013447980754263811,"nu":0,"particle_id":284,"point":[-0.1208678341594148,0.9804772633125474,0.1961057182849126],"type":1,"volume":0.013447980754263811},{"fixed":false,"mass":0.02343919615845805,"nu":0,"particle_id":285,"point":[-0.000996725570332032,0.9899379122074039,-0.1021620918133083],"type":1,"volume":0.02343919615845805},{"fixed":false,"mass":0.031735324375432764,"nu":0,"particle_id":286,"point":[3.046994056986258,-0.27284413587787,0.2805486740089123],"type":1,"volume":0.031735324375432764},{"fixed":false,"mass":0.039072354941713475,"nu":0,"particle_id":287,"point":[3.380334696081101,-0.2337664317222884,0.492141658370375],"type":1,"volume":0.039072354941713475},{"fixed":false,"mass":0.04169501640729936,"nu":0,"particle_id":288,"point":[3.539639079218827,-0.2621639002949371,0.1888879882133574],"type":1,"volume":0.04169501640729936},{"fixed":false,"mass":0.05323534978424636,"nu":0,"particle_id":289,"point":[3.427630485844607,0.03704443987088646,0.2968284008021886],"type":1,"volume":0.05323534978424636},{"fixed":false,"mass":0.028991002883315596,"nu":0,"particle_id":290,"point":[-3.41416270451684,-0.4075758565052182,0.9105742546075777],"type":1,"volume":0.028991002883315596},{"fixed":false,"mass":0.01842891734161891,"nu":0,"particle_id":291,"point":[-3.289065043702408,-0.7010478329735143,0.7120792314797131],"type":1,"volume":0.01842891734161891},{"fixed":false,"mass":0.06967913169906889,"nu":0,"particle_id":292,"point":[-3.141320592060944,-0.2067330264623866,0.4632097902880986],"type":1,"volume":0.06967913169906889},{"fixed":false,"mass":0.03851907858295996,"nu":0,"particle_id":293,"point":[-2.962680613100149,-0.5571584134869701,0.830166226276968],"type":1,"volume":0.03851907858295996},{"fixed":false,"mass":0.011301215276519715,"nu":0,"particle_id":294,"point":[-3.533105913957828,-0.8706849070978435,0.4822035767280699],"type":1,"volume":0.011301215276519715},{"fixed":false,"mass":0.023715312126495674,"nu":0,"particle_id":295,"point":[-2.7990610233493,-0.4872616384065535,-0.8679813168043682],"type":1,"volume":0.023715312126495674},{"fixed":false,"mass":0.01617401185644291,"nu":0,"particle_id":296,"point":[-2.582530223245836,-0.2910931602588515,-0.951663137805408],"type":1,"volume":0.01617401185644291},{"fixed":false,"mass":0.04257179210822027,"nu":0,"particle_id":297,"point":[1.037985217786788,-0.002765015927167158,0.4745215382095789],"type":1,"volume":0.04257179210822027},{"fixed":false,"mass":0.03715949497904096,"nu":0,"particle_id":298,"point":[1.370506280614356,0.059701080397356,0.7259277672007878],"type":1,"volume":0.03715949497904096},{"fixed":false,"mass":0.037060557850992853,"nu":0,"particle_id":299,"point":[1.090142894490899,0.3084672600958548,0.6084266814381483],"type":1,"volume":0.037060557850992853},{"fixed":false,"mass":0.01917182863948494,"nu":0,"particle_id":300,"point":[1.163038135298975,0.1533766912592376,0.9848937144355991],"type":1,"volume":0.01917182863948494},{"fixed":false,"mass":0.045574511489821334,"nu":0,"particle_id":301,"point":[-0.7285076075350403,-0.6174674067085624,-0.2383004976020995],"type":1,"volume":0.045574511489821334},{"fixed":false,"mass":0.02467712863116148,"nu":0,"particle_id":302,"point":[-0.5913762356818428,-0.6328143140029423,-0.7680770333224666],"type":1,"volume":0.02467712863116148},{"fixed":false,"mass":0.04868572853119623,"nu":0,"particle_id":303,"point":[-0.413921160710782,-0.5624826759007344,-0.4484830759148495],"type":1,"volume":0.04868572853119623},{"fixed":false,"mass":0.034838045457373304,"nu":0,"particle_id":304,"point":[0.3785156675896414,0.1400715661890727,-0.2444219661439481],"type":1,"volume":0.034838045457373304},{"fixed":false,"mass":0.04155395449464261,"nu":0,"particle_id":305,"point":[0.2083987429016033,0.3191937298527597,0.005760947279249168],"type":1,"volume":0.04155395449464261},{"fixed":false,"mass":0.03913883011427364,"nu":0,"particle_id":306,"point":[0.5361023210272371,0.02131892417865922,0.04943608176889605],"type":1,"volume":0.03913883011427364},{"fixed":false,"mass":0.040205054380362544,"nu":0,"particle_id":307,"point":[4.585145896611925,-0.09887219175157656,-0.03820606121951187],"type":1,"volume":0.040205054380362544},{"fixed":false,"mass":0.03485450349323851,"nu":0,"particle_id":308,"point":[4.314233451172206,-0.1345956692580633,-0.2037649898648881],"type":1,"volume":0.03485450349323851},{"fixed":false,"mass":0.0405465157527426,"nu":0,"particle_id":309,"point":[4.690446860841035,0.03137257093361137,-0.3342867086050328],"type":1,"volume":0.0405465157527426},{"fixed":false,"mass":0.04109690470815112,"nu":0,"particle_id":310,"point":[4.508464180579515,-0.2334731699170505,-0.4373825029302116],"type":1,"volume":0.04109690470815112},{"fixed":false,"mass":0.03803992530278079,"nu":0,"particle_id":311,"point":[0.5570757237958459,-0.1083475640350249,-0.4224459468757631],"type":1,"volume":0.03803992530278079},{"fixed":false,"mass":0.04956086576069051,"nu":0,"particle_id":312,"point":[0.747142901391881,0.1001585778732168,-0.6520264806568804],"type":1,"volume":0.04956086576069051},{"fixed":false,"mass":0.033312801606461356,"nu":0,"particle_id":313,"point":[0.8703640216531715,-0.1526190573867122,-0.3608695310141254],"type":1,"volume":0.033312801606461356},{"fixed":false,"mass":0.0382424824897758,"nu":0,"particle_id":314,"point":[0.7354043907382048,-0.3190995977528188,-0.6188114193398824],"type":1,"volume":0.0382424824897758},{"fixed":false,"mass":0.044331750336704945,"nu":0,"particle_id":315,"point":[1.950286630429806,0.5962102966710449,0.1818607547557189],"type":1,"volume":0.044331750336704945},{"fixed":false,"mass":0.017503953949638294,"nu":0,"particle_id":316,"point":[-2.459625541229079,0.9442279257631171,-0.3156037695520635],"type":1,"volume":0.017503953949638294},{"fixed":false,"mass":0.050042088308853996,"nu":0,"particle_id":317,"point":[-2.331828034996342,0.6263585724365436,-0.2107849042854773],"type":1,"volume":0.050042088308853996},{"fixed":false,"mass":0.04685726393157461,"nu":0,"particle_id":318,"point":[-4.318643377280324,-0.03721585132849892,-0.6734336720589975],"type":1,"volume":0.04685726393157461},{"fixed":false,"mass":0.02062489811624557,"nu":0,"particle_id":319,"point":[-2.775971894224293,-0.1406418867498619,0.9861479832032067],"type":1,"volume":0.02062489811624557},{"fixed":false,"mass":0.012736257790510037,"nu":0,"particle_id":320,"point":[-2.491567982740876,-0.122874237615914,0.9878979439007669],"type":1,"volume":0.012736257790510037},{"fixed":false,"mass":0.012732526270213929,"nu":0,"particle_id":321,"point":[-2.487426304122777,0.1620333051661782,0.9840411123835833],"type":1,"volume":0.012732526270213929},{"fixed":false,"mass":0.05217091744344,"nu":0,"particle_id":322,"point":[3.034865247795092,0.05111847672681612,0.3408437517252455],"type":1,"volume":0.05217091744344},{"fixed":false,"mass":0.04603226034249329,"nu":0,"particle_id":323,"point":[1.392642899986337,0.02594223683769051,-0.610495863305347],"type":1,"volume":0.04603226034249329},{"fixed":false,"mass":0.015094702065701376,"nu":0,"particle_id":324,"point":[3.841580470403831,0.9509856974164272,0.2933263819342138],"type":1,"volume":0.015094702065701376},{"fixed":false,"mass":0.044705132190868115,"nu":0,"particle_id":325,"point":[-1.727893218783428,0.07660112843950537,0.6329606405124966],"type":1,"volume":0.044705132190868115},{"fixed":false,"mass":0.0641943703725775,"nu":0,"particle_id":326,"point":[-1.911482224420938,-0.2148650664989057,0.4734562609665851],"type":1,"volume":0.0641943703725775},{"fixed":false,"mass":0.039408509014700076,"nu":0,"particle_id":327,"point":[-1.51431670758116,-0.2792571772671046,0.63874613481934],"type":1,"volume":0.039408509014700076},{"fixed":false,"mass":0.026310975436162776,"nu":0,"particle_id":328,"point":[-1.712143276096106,-0.3916383977681603,0.9190930037812916],"type":1,"volume":0.026310975436162776},{"fixed":false,"mass":0.04887845482535269,"nu":0,"particle_id":329,"point":[4.356458132099592,-0.547513193147888,-0.3433335058117309],"type":1,"volume":0.04887845482535269},{"fixed":false,"mass":0.04367299571527408,"nu":0,"particle_id":330,"point":[4.085196157355436,-0.3573049399097361,-0.1990769625206552],"type":1,"volume":0.04367299571527408},{"fixed":false,"mass":0.0636243158859831,"nu":0,"particle_id":331,"point":[4.489546188333659,-0.5381907892672536,-0.007516813406451939],"type":1,"volume":0.0636243158859831},{"fixed":false,"mass":0.035991860167817934,"nu":0,"particle_id":332,"point":[0.03738686014610853,0.5642790532197781,0.3560629448646393],"type":1,"volume":0.035991860167817934},{"fixed":false,"mass":0.036926800996912666,"nu":0,"particle_id":333,"point":[0.4072064387094109,0.3976305747268796,0.5664986690901241],"type":1,"volume":0.036926800996912666},{"fixed":false,"mass":0.06385701873800281,"nu":0,"particle_id":334,"point":[0.3515777967235877,0.4926195980447557,0.2380324931369928],"type":1,"volume":0.06385701873800281},{"fixed":false,"mass":0.03670984583469253,"nu":0,"particle_id":335,"point":[4.740171750404889,0.6876794865911354,0.02087165044012332],"type":1,"volume":0.03670984583469253},{"fixed":false,"mass":0.010298521272634505,"nu":0,"particle_id":336,"point":[5,0.9853602136405565,0.1486402453456225],"type":2,"volume":0.010298521272634505},{"fixed":false,"mass":0.009419268015331406,"nu":0,"particle_id":337,"point":[5,0.9853602136405567,-0.1486402453456203],"type":2,"volume":0.009419268015331406},{"fixed":false,"mass":0.042965598805804237,"nu":0,"particle_id":338,"point":[-3.710210700033557,0.2784459913099164,-0.5884139261818745],"type":1,"volume":0.042965598805804237},{"fixed":false,"mass":0.047788826743932575,"nu":0,"particle_id":339,"point":[-3.580522817122302,0.3343942818497538,-0.2489426082059625],"type":1,"volume":0.047788826743932575},{"fixed":false,"mass":0.03743291154431926,"nu":0,"particle_id":340,"point":[-3.250467323690525,0.3757941972740365,-0.5900663434293696],"type":1,"volume":0.03743291154431926},{"fixed":false,"mass":0.03090825032262339,"nu":0,"particle_id":341,"point":[-3.638148916256764,0.5680580992020869,-0.4645562622237233],"type":1,"volume":0.03090825032262339},{"fixed":false,"mass":0.01839384261228336,"nu":0,"particle_id":342,"point":[-5,-0.2025311025647999,0.2296650809018178],"type":3,"volume":0.01839384261228336},{"fixed":false,"mass":0.04940409616036986,"nu":0,"particle_id":343,"point":[-4.672852058809136,0.0460226436994011,0.3005205265808617],"type":1,"volume":0.04940409616036986},{"fixed":false,"mass":0.006315179623792932,"nu":0,"particle_id":344,"point":[-5,0.125370815588424,0.2522376120795907],"type":3,"volume":0.006315179623792932},{"fixed":false,"mass":0.01902573833844286,"nu":0,"particle_id":345,"point":[-5,-0.05382270361391531,0.4725068506284891],"type":3,"volume":0.01902573833844286},{"fixed":false,"mass":0.028569052229710203,"nu":0,"particle_id":346,"point":[3.900797496534923,-0.09523261260998354,0.9906204063386734],"type":1,"volume":0.028569052229710203},{"fixed":false,"mass":0.057461352614976605,"nu":0,"particle_id":347,"point":[4.133395722285912,-0.3647562975157106,0.5337670178919192],"type":1,"volume":0.057461352614976605},{"fixed":false,"mass":0.06036871369242387,"nu":0,"particle_id":348,"point":[4.175212820912298,0.05596745584691704,0.5839667438079432],"type":1,"volume":0.06036871369242387},{"fixed":false,"mass":0.02301461728624142,"nu":0,"particle_id":349,"point":[4.236222097531536,-0.1804358469864153,0.9822286202143693],"type":1,"volume":0.02301461728624142},{"fixed":false,"mass":0.0450064670208678,"nu":0,"particle_id":350,"point":[1.341499219372383,-0.3618337356917706,-0.5414755908182005],"type":1,"volume":0.0450064670208678},{"fixed":false,"mass":0.023884981639067746,"nu":0,"particle_id":351,"point":[1.545016859397928,-0.2661613159416563,-0.959226130095244],"type":1,"volume":0.023884981639067746},{"fixed":false,"mass":0.011566405153186776,"nu":0,"particle_id":352,"point":[1.729320319362443,0.5843426770600588,-0.8078566777182377],"type":1,"volume":0.011566405153186776},{"fixed":false,"mass":0.019363235853521222,"nu":0,"particle_id":353,"point":[1.708941597493081,0.787452600965811,-0.6092051165192587],"type":1,"volume":0.019363235853521222},{"fixed":false,"mass":0.03991609829760075,"nu":0,"particle_id":354,"point":[1.579261957549237,0.3204408656479726,-0.6347074933951168],"type":1,"volume":0.03991609829760075},{"fixed":false,"mass":0.03831143393800186,"nu":0,"particle_id":355,"point":[1.938088268539215,0.4694292280994222,-0.5340558335654607],"type":1,"volume":0.03831143393800186},{"fixed":false,"mass":0.04001281013677298,"nu":0,"particle_id":356,"point":[-4.447057404060107,-0.3549381497400995,0.2057938865047611],"type":1,"volume":0.04001281013677298},{"fixed":false,"mass":0.04590787568875264,"nu":0,"particle_id":357,"point":[-4.589023769272549,-0.1547098918652496,0.5619252217939441],"type":1,"volume":0.04590787568875264},{"fixed":false,"mass":0.03745264442923401,"nu":0,"particle_id":358,"point":[-4.721797974124273,-0.2866258227502707,0.02074317021649211],"type":1,"volume":0.03745264442923401},{"fixed":false,"mass":0.014151267695869857,"nu":0,"particle_id":359,"point":[-5,-0.4567777755027361,-0.8842752809932557],"type":3,"volume":0.014151267695869857},{"fixed":false,"mass":0.012138588018936605,"nu":0,"particle_id":360,"point":[-4.662319157509547,-0.1448229636338084,-0.9857361830733626],"type":1,"volume":0.012138588018936605},{"fixed":false,"mass":0.052855701808392046,"nu":0,"particle_id":361,"point":[-4.697544488685924,-0.3699699232032009,-0.527921882709032],"type":1,"volume":0.052855701808392046},{"fixed":false,"mass":0.025055018753701783,"nu":0,"particle_id":362,"point":[-4.536230404242893,-0.3199634103958382,-0.942905443171439],"type":1,"volume":0.025055018753701783},{"fixed":false,"mass":0.025393376044373632,"nu":0,"particle_id":363,"point":[5,0,0],"type":2,"volume":0.025393376044373632},{"fixed":false,"mass":0.021378411499744357,"nu":0,"particle_id":364,"point":[5,0.03902474269705655,-0.4684806111251374],"type":2,"volume":0.021378411499744357},{"fixed":false,"mass":0.03113921631174114,"nu":0,"particle_id":365,"point":[5,-0.4207833844029978,-0.2104427790538431],"type":2,"volume":0.03113921631174114},{"fixed":false,"mass":0.01543743867839918,"nu":0,"particle_id":366,"point":[2.206637845530393,0.5997176210975868,-0.7952387872364595],"type":1,"volume":0.01543743867839918},{"fixed":false,"mass":0.028590355143681755,"nu":0,"particle_id":367,"point":[1.931949365334744,0.3452190592570977,-0.9352442258470243],"type":1,"volume":0.028590355143681755},{"fixed":false,"mass":0.018267611636915187,"nu":0,"particle_id":368,"point":[2.258507045259502,0.2605619925546478,-0.9609246662751385],"type":1,"volume":0.018267611636915187},{"fixed":false,"mass":0.060260346730540024,"nu":0,"particle_id":369,"point":[2.253935410917276,0.30121671137991,-0.473218415106275],"type":1,"volume":0.060260346730540024},{"fixed":false,"mass":0.06398977387639924,"nu":0,"particle_id":370,"point":[2.73206029191555,-0.3967816953683554,0.2376549984105568],"type":1,"volume":0.06398977387639924},{"fixed":false,"mass":0.02088828007760897,"nu":0,"particle_id":371,"point":[-2.978643579717544,-0.9933051418021752,-0.06797403600339623],"type":1,"volume":0.02088828007760897},{"fixed":false,"mass":0.047590155802448846,"nu":0,"particle_id":372,"point":[-2.814006496248484,-0.4880689856103418,-0.148249113898269],"type":1,"volume":0.047590155802448846},{"fixed":false,"mass":0.022828969093572883,"nu":0,"particle_id":373,"point":[-2.791504694226523,-0.9801273813678559,0.1972591244818448],"type":1,"volume":0.022828969093572883},{"fixed":false,"mass":0.012603960230614471,"nu":0,"particle_id":374,"point":[-2.627666658230266,-0.9932265612354176,-0.06877187788683975],"type":1,"volume":0.012603960230614471},{"fixed":false,"mass":0.043037198380388636,"nu":0,"particle_id":375,"point":[0.9115676193396726,-0.002685776811705065,-0.07851611311025196],"type":1,"volume":0.043037198380388636},{"fixed":false,"mass":0.006717422415061768,"nu":0,"particle_id":376,"point":[-0.532065219844697,-0.4860992365044338,0.8686026335655014],"type":1,"volume":0.006717422415061768},{"fixed":false,"mass":0.016383203778620233,"nu":0,"particle_id":377,"point":[-0.5675407935454168,-0.7189036570879586,0.6927322463097543],"type":1,"volume":0.016383203778620233},{"fixed":false,"mass":0.05118925612109336,"nu":0,"particle_id":378,"point":[-0.5571060165041304,-0.2261067849269963,0.6234987577396465],"type":1,"volume":0.05118925612109336},{"fixed":false,"mass":0.03735022778530657,"nu":0,"particle_id":379,"point":[-2.564318858102155,0.4073797660171691,0.5488586962292776],"type":1,"volume":0.03735022778530657},{"fixed":false,"mass":0.027168730888564564,"nu":0,"particle_id":380,"point":[-4.428801278961851,0.7242735657018197,-0.1914555925305861],"type":1,"volume":0.027168730888564564},{"fixed":false,"mass":0.02198796520611299,"nu":0,"particle_id":381,"point":[-4.226881956461579,0.9194390652769016,-0.3909909622474873],"type":1,"volume":0.02198796520611299},{"fixed":false,"mass":0.014038881880449145,"nu":0,"particle_id":382,"point":[-4.208695566218871,0.992190978688664,-0.07928632393446365],"type":1,"volume":0.014038881880449145},{"fixed":false,"mass":0.08081085863473943,"nu":0,"particle_id":383,"point":[-4.004191517833799,0.5167772998588582,-0.3109854597287717],"type":1,"volume":0.08081085863473943},{"fixed":false,"mass":0.022508986917946172,"nu":0,"particle_id":384,"point":[-4.30784382452293,-0.8444285917881262,0.531325687651002],"type":1,"volume":0.022508986917946172},{"fixed":false,"mass":0.04747993325049497,"nu":0,"particle_id":385,"point":[-4.320655369665823,-0.6822850910370645,0.03555777760854781],"type":1,"volume":0.04747993325049497},{"fixed":false,"mass":0.061002608115571025,"nu":0,"particle_id":386,"point":[2.809098614311496,0.6697693849743858,0.04900032804593518],"type":1,"volume":0.061002608115571025},{"fixed":false,"mass":0.016834791916597126,"nu":0,"particle_id":387,"point":[2.785369587020907,0.9455884881606803,0.3111185964116037],"type":1,"volume":0.016834791916597126},{"fixed":false,"mass":0.01664624452123678,"nu":0,"particle_id":388,"point":[5,-0.5632090774271223,0.1044213632569307],"type":2,"volume":0.01664624452123678},{"fixed":false,"mass":0.03615096975852365,"nu":0,"particle_id":389,"point":[4.710524433397111,-0.6827536531471426,0.175116848553858],"type":1,"volume":0.03615096975852365},{"fixed":false,"mass":0.019945963716831466,"nu":0,"particle_id":390,"point":[5,-0.6466551408589429,-0.1183660943684787],"type":2,"volume":0.019945963716831466},{"fixed":false,"mass":0.010063866878470247,"nu":0,"particle_id":391,"point":[5,-1,0],"type":2,"volume":0.010063866878470247},{"fixed":false,"mass":0.03983312200929016,"nu":0,"particle_id":392,"point":[-4.560494651543501,0.008088466152775614,-0.01821127109030518],"type":1,"volume":0.03983312200929016},{"fixed":false,"mass":0.03685204908719612,"nu":0,"particle_id":393,"point":[-4.414031791449537,-0.2134100472394244,-0.3708040713153998],"type":1,"volume":0.03685204908719612},{"fixed":false,"mass":0.034323730602822365,"nu":0,"particle_id":394,"point":[-4.710155728110451,-0.08499596702793961,-0.2981915982054573],"type":1,"volume":0.034323730602822365},{"fixed":false,"mass":0.0640019219262844,"nu":0,"particle_id":395,"point":[0.02745076152495485,-0.2299890358911523,-0.4616266466204063],"type":1,"volume":0.0640019219262844},{"fixed":false,"mass":0.05969337362106137,"nu":0,"particle_id":396,"point":[-0.0951137418732172,-0.6067743331965254,-0.1726837287867926],"type":1,"volume":0.05969337362106137},{"fixed":false,"mass":0.05585581496050277,"nu":0,"particle_id":397,"point":[0.3111163298532363,-0.491082020812833,-0.1233598119262933],"type":1,"volume":0.05585581496050277},{"fixed":false,"mass":0.03937953826292331,"nu":0,"particle_id":398,"point":[4.477918636093202,-0.5265984523543372,0.4126456031989938],"type":1,"volume":0.03937953826292331},{"fixed":false,"mass":0.022598574110272232,"nu":0,"particle_id":399,"point":[4.311753942760346,-0.9826362757372568,0.1762968510030892],"type":1,"volume":0.022598574110272232},{"fixed":false,"mass":0.05950767006695242,"nu":0,"particle_id":400,"point":[2.278442841614884,-0.2354276625793917,0.4302086442113305],"type":1,"volume":0.05950767006695242},{"fixed":false,"mass":0.04106757605877499,"nu":0,"particle_id":401,"point":[2.322088034782306,-0.2631172838300679,-0.1640639023130168],"type":1,"volume":0.04106757605877499},{"fixed":false,"mass":0.06298627608632108,"nu":0,"particle_id":402,"point":[1.077347378240315,-0.3897389378410603,-0.2913480949132416],"type":1,"volume":0.06298627608632108},{"fixed":false,"mass":0.053482503683237016,"nu":0,"particle_id":403,"point":[0.6730289080436134,-0.5107944633950288,-0.3465260734420292],"type":1,"volume":0.053482503683237016},{"fixed":false,"mass":0.03972139538581521,"nu":0,"particle_id":404,"point":[1.768993225991768,0.6148119132803592,-0.1638673074320256],"type":1,"volume":0.03972139538581521},{"fixed":false,"mass":0.022800924022012798,"nu":0,"particle_id":405,"point":[1.655539738970316,0.9284683195155594,-0.3675562288970853],"type":1,"volume":0.022800924022012798},{"fixed":false,"mass":0.01611249513626628,"nu":0,"particle_id":406,"point":[1.980052879430746,0.9808808313846238,-0.194120176621338],"type":1,"volume":0.01611249513626628},{"fixed":false,"mass":0.03515769008064742,"nu":0,"particle_id":407,"point":[2.071424584289844,0.6759928660377171,-0.2797713635104553],"type":1,"volume":0.03515769008064742},{"fixed":false,"mass":0.016132613690641923,"nu":0,"particle_id":408,"point":[-0.6446894350648051,0.7887943560607247,0.6075701832056308],"type":1,"volume":0.016132613690641923},{"fixed":false,"mass":0.03231949329304842,"nu":0,"particle_id":409,"point":[-0.43192826830179,0.3342100765756691,0.6545802802801486],"type":1,"volume":0.03231949329304842},{"fixed":false,"mass":0.02012489832079343,"nu":0,"particle_id":410,"point":[-3.754867118730866,0.8685921403455626,-0.4861188679381553],"type":1,"volume":0.02012489832079343},{"fixed":false,"mass":0.016800027295851564,"nu":0,"particle_id":411,"point":[-3.300417531599843,0.943398894405177,-0.3183367196805481],"type":1,"volume":0.016800027295851564},{"fixed":false,"mass":0.037453292819736535,"nu":0,"particle_id":412,"point":[-1.112522089823344,0.3017013345375487,-0.5780981499053093],"type":1,"volume":0.037453292819736535},{"fixed":false,"mass":0.047313585348425884,"nu":0,"particle_id":413,"point":[-0.6115882585308059,0.3229258699490731,-0.600023484864719],"type":1,"volume":0.047313585348425884},{"fixed":false,"mass":0.03335603056923039,"nu":0,"particle_id":414,"point":[-2.978154521992757,0.003051322278755264,-0.004480898597038346],"type":1,"volume":0.03335603056923039},{"fixed":false,"mass":0.0606546404749683,"nu":0,"particle_id":415,"point":[-3.37321737107582,-0.08400421395439206,0.06860040149971734],"type":1,"volume":0.0606546404749683},{"fixed":false,"mass":0.04557886919987062,"nu":0,"particle_id":416,"point":[-3.242103227665906,0.1492752713496223,-0.24482126053117],"type":1,"volume":0.04557886919987062},{"fixed":false,"mass":0.039944307847752845,"nu":0,"particle_id":417,"point":[1.259662873253521,0.1510037883509702,0.2868813288780193],"type":1,"volume":0.039944307847752845},{"fixed":false,"mass":0.01819271541205241,"nu":0,"particle_id":418,"point":[-3.613068757098153,0.2531687027522975,-0.963167396217629],"type":1,"volume":0.01819271541205241},{"fixed":false,"mass":0.022870917992108584,"nu":0,"particle_id":419,"point":[-3.133923347589175,0.2267399593462462,-0.971184467881764],"type":1,"volume":0.022870917992108584},{"fixed":false,"mass":0.05889029145590221,"nu":0,"particle_id":420,"point":[-3.398673230577943,0.0831847652997855,-0.5911328706184457],"type":1,"volume":0.05889029145590221},{"fixed":false,"mass":0.017500497670000666,"nu":0,"particle_id":421,"point":[-3.585985467785876,-0.09412675486283326,-0.9907293238201038],"type":1,"volume":0.017500497670000666},{"fixed":false,"mass":0.052421519794763345,"nu":0,"particle_id":422,"point":[-3.520331713290353,-0.1031247569727718,0.5847785547018767],"type":1,"volume":0.052421519794763345},{"fixed":false,"mass":0.027717620711845792,"nu":0,"particle_id":423,"point":[-3.851719561803271,0.000519572404737601,0.9999488265847117],"type":1,"volume":0.027717620711845792},{"fixed":false,"mass":0.054696097829221066,"nu":0,"particle_id":424,"point":[-3.865055585669245,0.1938382381728525,0.5352766557450243],"type":1,"volume":0.054696097829221066},{"fixed":false,"mass":0.010198103823118329,"nu":0,"particle_id":425,"point":[0.5590431797597235,-0.4294312848916906,-0.8988922847540333],"type":1,"volume":0.010198103823118329},{"fixed":false,"mass":0.014098215057037915,"nu":0,"particle_id":426,"point":[0.6265019694669411,-0.6668448551387852,-0.740148889971858],"type":1,"volume":0.014098215057037915},{"fixed":false,"mass":0.023664874454881947,"nu":0,"particle_id":427,"point":[-0.03324676831345631,0.2788948494544816,0.9553634549335254],"type":1,"volume":0.023664874454881947},{"fixed":false,"mass":0.012378415472704223,"nu":0,"particle_id":428,"point":[2.428557509161417,-0.9699350137475129,-0.2308588576292035],"type":1,"volume":0.012378415472704223},{"fixed":false,"mass":0.04274203615830344,"nu":0,"particle_id":429,"point":[2.57468900653506,-0.683059316819491,-0.1174635100570868],"type":1,"volume":0.04274203615830344},{"fixed":false,"mass":0.014453711025124294,"nu":0,"particle_id":430,"point":[2.718160042761412,-0.9178845198448603,-0.3938993121909842],"type":1,"volume":0.014453711025124294},{"fixed":false,"mass":0.01941518489134874,"nu":0,"particle_id":431,"point":[2.378453105279212,-0.804057514410917,-0.5889719709443135],"type":1,"volume":0.01941518489134874},{"fixed":false,"mass":0.04071559297329217,"nu":0,"particle_id":432,"point":[3.447817049312609,-0.03522491705447164,-0.2792058208416099],"type":1,"volume":0.04071559297329217},{"fixed":false,"mass":0.044590031729158146,"nu":0,"particle_id":433,"point":[2.445730129791569,0.5863912580845965,-0.3732108356234886],"type":1,"volume":0.044590031729158146},{"fixed":false,"mass":0.015378274836822812,"nu":0,"particle_id":434,"point":[2.310244143749077,0.9315357944225086,-0.3574441193118698],"type":1,"volume":0.015378274836822812},{"fixed":false,"mass":0.02148076520845459,"nu":0,"particle_id":435,"point":[2.666796291042784,0.7273709403363537,-0.6824148318194327],"type":1,"volume":0.02148076520845459},{"fixed":false,"mass":0.04133782056293413,"nu":0,"particle_id":436,"point":[-4.69524177783212,0.2373800521041662,-0.2202644004813641],"type":1,"volume":0.04133782056293413},{"fixed":false,"mass":0.020324137775081602,"nu":0,"particle_id":437,"point":[-5,0.1616044704709591,-0.5700737751341308],"type":3,"volume":0.020324137775081602},{"fixed":false,"mass":0.04061680154459365,"nu":0,"particle_id":438,"point":[-4.548862035365133,0.1961379378517809,-0.5176344486287131],"type":1,"volume":0.04061680154459365},{"fixed":false,"mass":0.04735345134923272,"nu":0,"particle_id":439,"point":[-0.3388416081805412,0.6648127596524501,0.120505255187447],"type":1,"volume":0.04735345134923272},{"fixed":false,"mass":0.013953659269746517,"nu":0,"particle_id":440,"point":[-0.5452479977520281,0.9904632078045408,-0.09682867611171558],"type":1,"volume":0.013953659269746517},{"fixed":false,"mass":0.017808636466926018,"nu":0,"particle_id":441,"point":[-0.4426534452573045,0.9321214446481869,-0.3555134892528439],"type":1,"volume":0.017808636466926018},{"fixed":false,"mass":0.027879144026445857,"nu":0,"particle_id":442,"point":[-1.219999225300293,-0.9826473817962202,-0.1761840892940956],"type":1,"volume":0.027879144026445857},{"fixed":false,"mass":0.05575955248580224,"nu":0,"particle_id":443,"point":[-1.154730006596523,-0.5793295932242937,-0.2755252568805653],"type":1,"volume":0.05575955248580224},{"fixed":false,"mass":0.07801429770920942,"nu":0,"particle_id":444,"point":[-0.9447288133045737,-0.5139965262822277,0.04571164722727455],"type":1,"volume":0.07801429770920942},{"fixed":false,"mass":0.025081747484748063,"nu":0,"particle_id":445,"point":[-0.8053909985425183,-0.9829296246531509,-0.1733184294769953],"type":1,"volume":0.025081747484748063},{"fixed":false,"mass":0.017937456587034387,"nu":0,"particle_id":446,"point":[3.994853660083982,0.1049011164055397,-0.989668141831485],"type":1,"volume":0.017937456587034387},{"fixed":false,"mass":0.03247094719903049,"nu":0,"particle_id":447,"point":[3.997985655144568,0.2633370796371267,-0.6911693397018224],"type":1,"volume":0.03247094719903049},{"fixed":false,"mass":0.06040415250259707,"nu":0,"particle_id":448,"point":[4.207439147045226,0.01554936484689754,-0.5965977697630661],"type":1,"volume":0.06040415250259707},{"fixed":false,"mass":0.01438168143433031,"nu":0,"particle_id":449,"point":[2.263606934511956,0.7950919105072195,-0.5998965909099947],"type":1,"volume":0.01438168143433031},{"fixed":false,"mass":0.017759452248747004,"nu":0,"particle_id":450,"point":[2.816199481080052,-0.2284475039513554,-0.9706664898886925],"type":1,"volume":0.017759452248747004},{"fixed":false,"mass":0.0299842589861546,"nu":0,"particle_id":451,"point":[3.229861540020519,0.08410408032684925,-0.9917164711005448],"type":1,"volume":0.0299842589861546},{"fixed":false,"mass":0.029785228345060564,"nu":0,"particle_id":452,"point":[3.075442681567607,-0.01455403286748605,-0.6897068353124263],"type":1,"volume":0.029785228345060564},{"fixed":false,"mass":0.027996037004204822,"nu":0,"particle_id":453,"point":[3.189825676412912,-0.409731831999987,-0.9094218616967864],"type":1,"volume":0.027996037004204822},{"fixed":false,"mass":0.025208814309946814,"nu":0,"particle_id":454,"point":[-2.036281963727589,-0.6088537639615936,0.7877409485579903],"type":1,"volume":0.025208814309946814},{"fixed":false,"mass":0.017562275302873673,"nu":0,"particle_id":455,"point":[-1.695935859263936,-0.7200993717854909,0.691275263735214],"type":1,"volume":0.017562275302873673},{"fixed":false,"mass":0.0406420791798831,"nu":0,"particle_id":456,"point":[-2.811993666109769,-0.2597511634454077,0.07854231117968707],"type":1,"volume":0.0406420791798831},{"fixed":false,"mass":0.04571252931514123,"nu":0,"particle_id":457,"point":[-2.572743561714617,-0.05376914495645748,0.01610654019603835],"type":1,"volume":0.04571252931514123},{"fixed":false,"mass":0.039631962286871374,"nu":0,"particle_id":458,"point":[3.022141045749324,0.2569636609926702,-0.2287952446625661],"type":1,"volume":0.039631962286871374},{"fixed":false,"mass":0.04179941052260108,"nu":0,"particle_id":459,"point":[3.255614924914051,-0.0272716946151466,0.01399139804825961],"type":1,"volume":0.04179941052260108},{"fixed":false,"mass":0.02281794265844556,"nu":0,"particle_id":460,"point":[3.368884562017886,-0.9200539089285176,-0.3898406706814885],"type":1,"volume":0.02281794265844556},{"fixed":false,"mass":0.010285199633551413,"nu":0,"particle_id":461,"point":[3.26357138698309,-0.9851749209552969,-0.1505215535506417],"type":1,"volume":0.010285199633551413},{"fixed":false,"mass":0.052458738232886624,"nu":0,"particle_id":462,"point":[4.541206227887655,0.2039009937173035,-0.5829850841061374],"type":1,"volume":0.052458738232886624},{"fixed":false,"mass":0.03224983897490185,"nu":0,"particle_id":463,"point":[3.80168239016323,-0.1867425074350222,-0.2333090093059733],"type":1,"volume":0.03224983897490185},{"fixed":false,"mass":0.05533600753447479,"nu":0,"particle_id":464,"point":[4.062766087814739,-0.03731500437118657,0.05991677350780944],"type":1,"volume":0.05533600753447479},{"fixed":false,"mass":0.034914452075423374,"nu":0,"particle_id":465,"point":[3.65656083354117,0.0003531149005125966,0.0003111835130313878],"type":1,"volume":0.034914452075423374},{"fixed":false,"mass":0.016919385544027447,"nu":0,"particle_id":466,"point":[2.893397203498036,0.774352838682328,0.6251672230460473],"type":1,"volume":0.016919385544027447},{"fixed":false,"mass":0.06575598251780737,"nu":0,"particle_id":467,"point":[3.02078432439836,0.4913851656163602,0.3111328545639421],"type":1,"volume":0.06575598251780737},{"fixed":false,"mass":0.014859386991627425,"nu":0,"particle_id":468,"point":[2.637270369251912,0.8453116323520437,0.5296736349536404],"type":1,"volume":0.014859386991627425},{"fixed":false,"mass":0.013876176885519875,"nu":0,"particle_id":469,"point":[2.97806001000529,0.8113861621566576,-0.5800419878283367],"type":1,"volume":0.013876176885519875},{"fixed":false,"mass":0.06174049086691122,"nu":0,"particle_id":470,"point":[0.7068104481280483,-0.2243531098636304,0.5752048577472375],"type":1,"volume":0.06174049086691122},{"fixed":false,"mass":0.04959060131929213,"nu":0,"particle_id":471,"point":[0.7772684143886415,0.1710226405681259,0.6355389761459849],"type":1,"volume":0.04959060131929213},{"fixed":false,"mass":0.043232796894229694,"nu":0,"particle_id":472,"point":[0.8003952306630803,0.131330301988912,0.2531303667538218],"type":1,"volume":0.043232796894229694},{"fixed":false,"mass":0.012209413875634787,"nu":0,"particle_id":473,"point":[-0.2224177716256706,-0.8719936376773831,-0.4797551140272662],"type":1,"volume":0.012209413875634787},{"fixed":false,"mass":0.018954974705104474,"nu":0,"particle_id":474,"point":[-0.1280590308114988,-0.7000458525898701,-0.7129015355293963],"type":1,"volume":0.018954974705104474},{"fixed":false,"mass":0.06476475167987937,"nu":0,"particle_id":475,"point":[-2.905801082478374,-0.5028141966058933,0.2674548847084701],"type":1,"volume":0.06476475167987937},{"fixed":false,"mass":0.056441690567067444,"nu":0,"particle_id":476,"point":[-0.3929927291104882,0.5621294743796047,-0.2011320872011412],"type":1,"volume":0.056441690567067444},{"fixed":false,"mass":0.0479433544440213,"nu":0,"particle_id":477,"point":[-1.651768059945895,-0.4899939981822175,0.379793677962541],"type":1,"volume":0.0479433544440213},{"fixed":false,"mass":0.015306320962243578,"nu":0,"particle_id":478,"point":[4.374144617168078,0.9999999999999999,1.169138000865524e-15],"type":1,"volume":0.015306320962243578},{"fixed":false,"mass":0.017351920375610824,"nu":0,"particle_id":479,"point":[4.208742164198657,0.9576523213241108,-0.2713494681654346],"type":1,"volume":0.017351920375610824},{"fixed":false,"mass":0.04937110999067572,"nu":0,"particle_id":480,"point":[1.016920108016674,-0.415383297645586,0.4031391964212584],"type":1,"volume":0.04937110999067572},{"fixed":false,"mass":0.021273832654346424,"nu":0,"particle_id":481,"point":[0.6947391947538961,-0.5296134437959139,0.8453438051961342],"type":1,"volume":0.021273832654346424},{"fixed":false,"mass":0.04676399282005567,"nu":0,"particle_id":482,"point":[0.677153210482357,-0.5272583385963083,0.3936744912652289],"type":1,"volume":0.04676399282005567},{"fixed":false,"mass":0.015675498797122055,"nu":0,"particle_id":483,"point":[-4.339812456980797,0.2666893534725878,-0.9590659516614156],"type":1,"volume":0.015675498797122055},{"fixed":false,"mass":0.021230337076012632,"nu":0,"particle_id":484,"point":[3.894480192339681,0.9760602252411635,-0.2106667413983267],"type":1,"volume":0.021230337076012632},{"fixed":false,"mass":0.022647585544825936,"nu":0,"particle_id":485,"point":[3.956212664494338,0.8747881983152965,-0.4745268588049645],"type":1,"volume":0.022647585544825936},{"fixed":false,"mass":0.0103619045027685,"nu":0,"particle_id":486,"point":[2.033257175151563,-0.8827227190891273,-0.4596824145265175],"type":1,"volume":0.0103619045027685},{"fixed":false,"mass":0.013785296565029257,"nu":0,"particle_id":487,"point":[1.915577848510047,-0.9637153781564272,-0.2513622483936021],"type":1,"volume":0.013785296565029257},{"fixed":false,"mass":0.0526666798273384,"nu":0,"particle_id":488,"point":[1.343806725991137,-0.5040878158955332,0.1560164103242782],"type":1,"volume":0.0526666798273384},{"fixed":false,"mass":0.03986640602988994,"nu":0,"particle_id":489,"point":[1.082556841624721,-0.2717264821200776,0.0827164948580461],"type":1,"volume":0.03986640602988994},{"fixed":false,"mass":0.017640490989158836,"nu":0,"particle_id":490,"point":[-1.733956741602771,0.2749672353890485,0.956554883634764],"type":1,"volume":0.017640490989158836},{"fixed":false,"mass":0.02766498864293735,"nu":0,"particle_id":491,"point":[-1.361128442225207,-0.01066218867345667,0.7303852617724089],"type":1,"volume":0.02766498864293735},{"fixed":false,"mass":0.04955210910827252,"nu":0,"particle_id":492,"point":[-1.333790166875309,0.2942130838296303,0.6288405472562405],"type":1,"volume":0.04955210910827252},{"fixed":false,"mass":0.01797528158309501,"nu":0,"particle_id":493,"point":[-1.250869283970371,0.1539771342692995,0.9848345759609021],"type":1,"volume":0.01797528158309501},{"fixed":false,"mass":0.04396279092442496,"nu":0,"particle_id":494,"point":[-2.265391081355599,0.1529744002049249,-0.09036430898252702],"type":1,"volume":0.04396279092442496},{"fixed":false,"mass":0.050163322760476615,"nu":0,"particle_id":495,"point":[-2.241956820158258,0.3502363453955511,-0.4206415300488416],"type":1,"volume":0.050163322760476615},{"fixed":false,"mass":0.02575167093917805,"nu":0,"particle_id":496,"point":[-3.136783277752716,-0.2179694508519731,-0.9738449725470518],"type":1,"volume":0.02575167093917805},{"fixed":false,"mass":0.011309970724868636,"nu":0,"particle_id":497,"point":[-1.818439024254243,0.8537461153983048,-0.5138938270526173],"type":1,"volume":0.011309970724868636},{"fixed":false,"mass":0.03058736042521498,"nu":0,"particle_id":498,"point":[-2.15277942812303,0.9835426051258265,-0.1670947342936451],"type":1,"volume":0.03058736042521498},{"fixed":false,"mass":0.019010372374075202,"nu":0,"particle_id":499,"point":[-1.604268590324133,0.9496530354622581,-0.2977195796389685],"type":1,"volume":0.019010372374075202},{"fixed":false,"mass":0.016726673390743213,"nu":0,"particle_id":500,"point":[-1.647326914844132,0.9985606180271498,0.01461429042319919],"type":1,"volume":0.016726673390743213},{"fixed":false,"mass":0.009394243066383966,"nu":0,"particle_id":501,"point":[4.628890088155206,-0.2221001761570721,0.9725919307248572],"type":1,"volume":0.009394243066383966},{"fixed":false,"mass":0.024225132274510133,"nu":0,"particle_id":502,"point":[4.725482602881272,0.4310094934322792,-0.593136176883271],"type":1,"volume":0.024225132274510133},{"fixed":false,"mass":0.012223032328162938,"nu":0,"particle_id":503,"point":[2.286425764327157,0.6029019107182447,0.7926255082809313],"type":1,"volume":0.012223032328162938},{"fixed":false,"mass":0.01155763341512236,"nu":0,"particle_id":504,"point":[1.99102013065114,0.7001603885336615,0.7128075383095391],"type":1,"volume":0.01155763341512236},{"fixed":false,"mass":0.022173131698950115,"nu":0,"particle_id":505,"point":[2.355538214395486,0.8360967737307315,0.5469134228673583],"type":1,"volume":0.022173131698950115},{"fixed":false,"mass":0.039717707005458416,"nu":0,"particle_id":506,"point":[2.093154478320526,0.5190312617317041,0.46392629141071],"type":1,"volume":0.039717707005458416},{"fixed":false,"mass":0.013712349347936487,"nu":0,"particle_id":507,"point":[3.761473751494503,-0.9936496245037812,-0.06447644443840522],"type":1,"volume":0.013712349347936487},{"fixed":false,"mass":0.021052332299175268,"nu":0,"particle_id":508,"point":[3.912747963489887,-0.9828092080243522,0.1745410400266875],"type":1,"volume":0.021052332299175268},{"fixed":false,"mass":0.017931885420643327,"nu":0,"particle_id":509,"point":[-4.636204077663011,0.2666893534725878,-0.9590659516614157],"type":1,"volume":0.017931885420643327},{"fixed":false,"mass":0.016863290479398642,"nu":0,"particle_id":510,"point":[-4.488008267321904,0.5236851615008375,-0.8485125380999123],"type":1,"volume":0.016863290479398642},{"fixed":false,"mass":0.03214756883806146,"nu":0,"particle_id":511,"point":[0.4070381010421754,0.4996203715376544,-0.8613754363195506],"type":1,"volume":0.03214756883806146},{"fixed":false,"mass":0.01990353144872357,"nu":0,"particle_id":512,"point":[-0.1335097133684486,0.5692272680561492,-0.8202615733024472],"type":1,"volume":0.01990353144872357},{"fixed":false,"mass":0.022684281330445095,"nu":0,"particle_id":513,"point":[0.1966229918873446,0.2200803258148279,-0.97320464562756],"type":1,"volume":0.022684281330445095},{"fixed":false,"mass":0.06240784515583585,"nu":0,"particle_id":514,"point":[0.1311188848607186,0.2918113072550412,-0.4470501441594271],"type":1,"volume":0.06240784515583585},{"fixed":false,"mass":0.008513978417893323,"nu":0,"particle_id":515,"point":[-0.7308740232373951,-0.005608721072547262,-0.9994475891905259],"type":1,"volume":0.008513978417893323},{"fixed":false,"mass":0.02915552623996763,"nu":0,"particle_id":516,"point":[-0.5450983353557908,0.03870052886645936,-0.7387364160036708],"type":1,"volume":0.02915552623996763},{"fixed":false,"mass":0.01203006386780243,"nu":0,"particle_id":517,"point":[-0.6622708853378605,0.2689253571207114,-0.9583876673702234],"type":1,"volume":0.01203006386780243},{"fixed":false,"mass":0.04979248604473674,"nu":0,"particle_id":518,"point":[0.003929497586142593,-0.1814487657022003,0.571319202999107],"type":1,"volume":0.04979248604473674},{"fixed":false,"mass":0.047280593972269185,"nu":0,"particle_id":519,"point":[0.2403192462736594,0.06543553492009882,0.6820598034411298],"type":1,"volume":0.047280593972269185},{"fixed":false,"mass":0.04023988859568316,"nu":0,"particle_id":520,"point":[-0.2296568119078888,0.08210965018073563,0.6784961729714686],"type":1,"volume":0.04023988859568316},{"fixed":false,"mass":0.020961768636790327,"nu":0,"particle_id":521,"point":[-0.06602695259142422,-0.09493392728190987,0.9906498242757977],"type":1,"volume":0.020961768636790327},{"fixed":false,"mass":0.02120841971576497,"nu":0,"particle_id":522,"point":[-0.1711936368038592,0.2345240316616338,-0.9688231953599314],"type":1,"volume":0.02120841971576497},{"fixed":false,"mass":0.05346957087199773,"nu":0,"particle_id":523,"point":[-0.1846488820872028,0.04021294006929188,-0.6363033245293416],"type":1,"volume":0.05346957087199773},{"fixed":false,"mass":0.019542044866340525,"nu":0,"particle_id":524,"point":[-0.003618105374116314,-0.09652941896865216,-0.9904926820605258],"type":1,"volume":0.019542044866340525},{"fixed":false,"mass":0.04827320814187752,"nu":0,"particle_id":525,"point":[-0.7095973922532746,0.6716895887619997,-0.0957526663238627],"type":1,"volume":0.04827320814187752},{"fixed":false,"mass":0.013542010036038032,"nu":0,"particle_id":526,"point":[1.986410523639958,0.8282829495809576,-0.5594531927807165],"type":1,"volume":0.013542010036038032},{"fixed":false,"mass":0.044147265580980276,"nu":0,"particle_id":527,"point":[-2.547582594375717,-0.579079097423526,0.3919374798720334],"type":1,"volume":0.044147265580980276},{"fixed":false,"mass":0.017638096233961103,"nu":0,"particle_id":528,"point":[-2.707475554051676,-0.7159784671739545,0.6962966005329826],"type":1,"volume":0.017638096233961103},{"fixed":false,"mass":0.018511019721152055,"nu":0,"particle_id":529,"point":[-2.891202994743407,-0.8748895911650739,0.474337166125135],"type":1,"volume":0.018511019721152055},{"fixed":false,"mass":0.02406123613110912,"nu":0,"particle_id":530,"point":[-2.509110965855692,-0.9411375272483931,0.3257914481446679],"type":1,"volume":0.02406123613110912},{"fixed":false,"mass":0.03935627789735215,"nu":0,"particle_id":531,"point":[2.957877943202651,-0.2520975484547896,-0.03625138304485788],"type":1,"volume":0.03935627789735215},{"fixed":false,"mass":0.03853137919536009,"nu":0,"particle_id":532,"point":[3.029849096496132,-0.6056337158711895,0.3054503491134818],"type":1,"volume":0.03853137919536009},{"fixed":false,"mass":0.051108263425029284,"nu":0,"particle_id":533,"point":[2.316881885754631,-0.4996890365316228,-0.3993871482389644],"type":1,"volume":0.051108263425029284},{"fixed":false,"mass":0.04423260978131102,"nu":0,"particle_id":534,"point":[3.536309138901098,0.268974623571743,-0.1640437210979572],"type":1,"volume":0.04423260978131102},{"fixed":false,"mass":0.05023863472054144,"nu":0,"particle_id":535,"point":[3.253080577735389,0.4170510960554207,-0.05687348226694063],"type":1,"volume":0.05023863472054144},{"fixed":false,"mass":0.04717289044059461,"nu":0,"particle_id":536,"point":[-3.741461876280619,0.2456361921027218,0.06529531109390327],"type":1,"volume":0.04717289044059461},{"fixed":false,"mass":0.03608763036135959,"nu":0,"particle_id":537,"point":[-2.821955679438787,0.1766117065736001,-0.240300227855733],"type":1,"volume":0.03608763036135959},{"fixed":false,"mass":0.029514629521622364,"nu":0,"particle_id":538,"point":[-3.082059442334199,-0.6461558805725265,-0.2196586778874818],"type":1,"volume":0.029514629521622364},{"fixed":false,"mass":0.02539223080417045,"nu":0,"particle_id":539,"point":[-2.909948657189764,-0.8366622026525372,-0.5458555797584399],"type":1,"volume":0.02539223080417045},{"fixed":false,"mass":0.020963248016318894,"nu":0,"particle_id":540,"point":[-2.728692660583996,-0.9373156100753249,-0.3383906205754277],"type":1,"volume":0.020963248016318894},{"fixed":false,"mass":0.011248567803923628,"nu":0,"particle_id":541,"point":[-0.6247063411492171,0.6573933262539742,-0.7479055592685269],"type":1,"volume":0.011248567803923628},{"fixed":false,"mass":0.016983032690851198,"nu":0,"particle_id":542,"point":[-0.362224085468793,0.7649400730708279,-0.6366367111291935],"type":1,"volume":0.016983032690851198},{"fixed":false,"mass":0.018641358835003497,"nu":0,"particle_id":543,"point":[-0.4216044254491031,0.4581672381545899,-0.8835325977328519],"type":1,"volume":0.018641358835003497},{"fixed":false,"mass":0.01891793552677203,"nu":0,"particle_id":544,"point":[1.600031023415109,0.01205979252226091,-0.9988122141102864],"type":1,"volume":0.01891793552677203},{"fixed":false,"mass":0.01705899361680456,"nu":0,"particle_id":545,"point":[5,-0.364817421855669,0.9292991275486134],"type":2,"volume":0.01705899361680456},{"fixed":false,"mass":0.015197209352613228,"nu":0,"particle_id":546,"point":[5,0.04728569363338544,0.5906812234423682],"type":2,"volume":0.015197209352613228},{"fixed":false,"mass":0.04292547274804298,"nu":0,"particle_id":547,"point":[-1.64450599246049,-0.1915040440050406,0.1568344259840214],"type":1,"volume":0.04292547274804298},{"fixed":false,"mass":0.029696466736029232,"nu":0,"particle_id":548,"point":[0.2146318326314471,-0.06492480386264761,0.3297917971608947],"type":1,"volume":0.029696466736029232},{"fixed":false,"mass":0.045577608423644264,"nu":0,"particle_id":549,"point":[-4.163345387659064,0.2849947361830114,0.6214436032908858],"type":1,"volume":0.045577608423644264},{"fixed":false,"mass":0.00973900214028752,"nu":0,"particle_id":550,"point":[-4.125782776994046,0.4976742412994103,0.8624156646039027],"type":1,"volume":0.00973900214028752},{"fixed":false,"mass":0.01143922982599067,"nu":0,"particle_id":551,"point":[-3.817925322936671,0.2827707365612491,0.9541877174336512],"type":1,"volume":0.01143922982599067},{"fixed":false,"mass":0.023527874286853767,"nu":0,"particle_id":552,"point":[-3.784167697858088,0.5439094846653414,0.8377024121514174],"type":1,"volume":0.023527874286853767},{"fixed":false,"mass":0.04388231176186716,"nu":0,"particle_id":553,"point":[-1.293606783840107,0.1638433013873401,0.1609843774369132],"type":1,"volume":0.04388231176186716},{"fixed":false,"mass":0.04809917273211399,"nu":0,"particle_id":554,"point":[1.89301306111204,-0.3106255373779593,0.5198801542533201],"type":1,"volume":0.04809917273211399},{"fixed":false,"mass":0.053080351817791714,"nu":0,"particle_id":555,"point":[1.562429606129339,-0.08801092554998488,0.461492401442625],"type":1,"volume":0.053080351817791714},{"fixed":false,"mass":0.05222653556068314,"nu":0,"particle_id":556,"point":[1.545269664882321,-0.4723075794407531,0.4828778815287664],"type":1,"volume":0.05222653556068314},{"fixed":false,"mass":0.07792541214874571,"nu":0,"particle_id":557,"point":[-1.807980591251137,-0.2938145331485476,-0.4090541920152777],"type":1,"volume":0.07792541214874571},{"fixed":false,"mass":0.049364461267894524,"nu":0,"particle_id":558,"point":[-1.600832622137354,-0.0704847186387215,-0.6571433758671843],"type":1,"volume":0.049364461267894524},{"fixed":false,"mass":0.015418068730584539,"nu":0,"particle_id":559,"point":[1.242240150022864,0.6260424749744753,0.7736345379880352],"type":1,"volume":0.015418068730584539},{"fixed":false,"mass":0.016812290352757893,"nu":0,"particle_id":560,"point":[1.480229754070165,0.3946643690660081,0.9174755884255243],"type":1,"volume":0.016812290352757893},{"fixed":false,"mass":0.04493943373492948,"nu":0,"particle_id":561,"point":[1.443335446840895,0.3142590545117552,0.5050711087553296],"type":1,"volume":0.04493943373492948},{"fixed":false,"mass":0.01737019914603044,"nu":0,"particle_id":562,"point":[1.580544482588904,0.7220942787192464,0.688844462603213],"type":1,"volume":0.01737019914603044},{"fixed":false,"mass":0.013622587056140178,"nu":0,"particle_id":563,"point":[0.7913298262029058,-0.7903173653793729,-0.6057143909813545],"type":1,"volume":0.013622587056140178},{"fixed":false,"mass":0.021531480102973774,"nu":0,"particle_id":564,"point":[2.57834076600416,0.2835279679506066,0.9539580138029661],"type":1,"volume":0.021531480102973774},{"fixed":false,"mass":0.01944853763021792,"nu":0,"particle_id":565,"point":[2.60750789168714,0.6021785220832038,0.7932191779912361],"type":1,"volume":0.01944853763021792},{"fixed":false,"mass":0.055164263867054676,"nu":0,"particle_id":566,"point":[-0.813774583816688,0.5951641722279204,0.3558451274044628],"type":1,"volume":0.055164263867054676},{"fixed":false,"mass":0.00968753199860839,"nu":0,"particle_id":567,"point":[-5,0.3522506557514858,-0.2943188194355218],"type":3,"volume":0.00968753199860839},{"fixed":false,"mass":0.010326229312782612,"nu":0,"particle_id":568,"point":[-5,0.5202762034718468,-0.4374703851328893],"type":3,"volume":0.010326229312782612},{"fixed":false,"mass":0.03244027656744117,"nu":0,"particle_id":569,"point":[-4.741226403163841,0.6336329380306298,-0.2859049177918046],"type":1,"volume":0.03244027656744117},{"fixed":false,"mass":0.03933049221446621,"nu":0,"particle_id":570,"point":[-4.721722354569746,0.4487715602269916,-0.5471164750871407],"type":1,"volume":0.03933049221446621},{"fixed":false,"mass":0.04007824558857712,"nu":0,"particle_id":571,"point":[1.373764283709624,0.5989428693773198,0.3661544780066795],"type":1,"volume":0.04007824558857712},{"fixed":false,"mass":0.019426165094731065,"nu":0,"particle_id":572,"point":[1.21082881809085,0.9741127754804431,0.2170866228935245],"type":1,"volume":0.019426165094731065},{"fixed":false,"mass":0.013498784354166772,"nu":0,"particle_id":573,"point":[1.392587566193728,0.9952908266664198,0.04781303924062444],"type":1,"volume":0.013498784354166772},{"fixed":false,"mass":0.03662489592119974,"nu":0,"particle_id":574,"point":[1.420369469837462,0.6856418307328629,-0.1093638098464807],"type":1,"volume":0.03662489592119974},{"fixed":false,"mass":0.012442234754790341,"nu":0,"particle_id":575,"point":[0.598788074679274,-0.1896279578478199,-0.9813232763158151],"type":1,"volume":0.012442234754790341},{"fixed":false,"mass":0.038914751522463785,"nu":0,"particle_id":576,"point":[-4.719830011230203,0.141988227877589,0.6716124340263612],"type":1,"volume":0.038914751522463785},{"fixed":false,"mass":0.00946641076970521,"nu":0,"particle_id":577,"point":[-5,0.02787004600230285,0.9972550400576045],"type":3,"volume":0.00946641076970521},{"fixed":false,"mass":0.01839529007697833,"nu":0,"particle_id":578,"point":[-5,-0.2665543640538293,0.9591069002539181],"type":3,"volume":0.01839529007697833},{"fixed":false,"mass":0.00933855862616374,"nu":0,"particle_id":579,"point":[-4.692820789426184,-0.1206298150342927,0.9881190002305573],"type":1,"volume":0.00933855862616374},{"fixed":false,"mass":0.03653188473408369,"nu":0,"particle_id":580,"point":[1.909011927406466,-0.3500045198417168,-0.5873571514062431],"type":1,"volume":0.03653188473408369},{"fixed":false,"mass":0.013788320625464074,"nu":0,"particle_id":581,"point":[1.730310250498319,-0.6031556878067161,-0.7924172388068247],"type":1,"volume":0.013788320625464074},{"fixed":false,"mass":0.028790620233976844,"nu":0,"particle_id":582,"point":[1.68464738102339,-0.7968862900379108,-0.5977101331256044],"type":1,"volume":0.028790620233976844},{"fixed":false,"mass":0.008736790114574065,"nu":0,"particle_id":583,"point":[5,-0.9509775076979265,-0.2933533798179653],"type":2,"volume":0.008736790114574065},{"fixed":false,"mass":0.034993478079408356,"nu":0,"particle_id":584,"point":[-3.552746958378378,0.2576938651479107,0.6591892465978867],"type":1,"volume":0.034993478079408356},{"fixed":false,"mass":0.026820106738780054,"nu":0,"particle_id":585,"point":[0.3784544155502955,-0.1772691714553776,0.9825405105313982],"type":1,"volume":0.026820106738780054},{"fixed":false,"mass":0.018660745393431013,"nu":0,"particle_id":586,"point":[-1.984110237969525,0.9844260018005973,0.1581254573348489],"type":1,"volume":0.018660745393431013},{"fixed":false,"mass":0.03614642507241911,"nu":0,"particle_id":587,"point":[3.145871085886945,-0.4435259792903743,0.5574328258185868],"type":1,"volume":0.03614642507241911},{"fixed":false,"mass":0.027936926309293675,"nu":0,"particle_id":588,"point":[1.289706773375072,-0.1699523585732498,0.3088320686508029],"type":1,"volume":0.027936926309293675},{"fixed":false,"mass":0.042381339678673656,"nu":0,"particle_id":589,"point":[0.7273845165260759,0.696689893007059,-0.1548439284279397],"type":1,"volume":0.042381339678673656},{"fixed":false,"mass":0.008132582363846803,"nu":0,"particle_id":590,"point":[0.720970660116659,0.9935153603021663,0.06583965175436064],"type":1,"volume":0.008132582363846803},{"fixed":false,"mass":0.020144666246545304,"nu":0,"particle_id":591,"point":[1.021986199230513,0.994518522086614,0.05565437923052247],"type":1,"volume":0.020144666246545304},{"fixed":false,"mass":0.017798734221972673,"nu":0,"particle_id":592,"point":[0.8861194862111342,0.9067777962224608,-0.4146785305746067],"type":1,"volume":0.017798734221972673},{"fixed":false,"mass":0.014743734213202329,"nu":0,"particle_id":593,"point":[-4.596094902149025,-0.9979760723788782,-0.02054928198943803],"type":1,"volume":0.014743734213202329},{"fixed":false,"mass":0.024992877764363094,"nu":0,"particle_id":594,"point":[-4.253779846532244,-0.9827584740724715,-0.1750561504845662],"type":1,"volume":0.024992877764363094},{"fixed":false,"mass":0.041948390211997554,"nu":0,"particle_id":595,"point":[-4.743481358080667,-0.01198972799759832,-0.6844256476961705],"type":1,"volume":0.041948390211997554},{"fixed":false,"mass":0.061780780118433715,"nu":0,"particle_id":596,"point":[-1.535990154594185,0.004887382641169333,-0.1438831633069234],"type":1,"volume":0.061780780118433715},{"fixed":false,"mass":0.01652409290036778,"nu":0,"particle_id":597,"point":[3.121032967955424,0.9262871006803163,0.3747467437538976],"type":1,"volume":0.01652409290036778},{"fixed":false,"mass":0.011282800221159345,"nu":0,"particle_id":598,"point":[-4.488008267321904,-0.01122062559631444,-0.9988948648384737],"type":1,"volume":0.011282800221159345},{"fixed":false,"mass":0.0523840451889808,"nu":0,"particle_id":599,"point":[-1.146021661663344,0.2092623867327648,-0.185623015606248],"type":1,"volume":0.0523840451889808},{"fixed":false,"mass":0.04149801448433661,"nu":0,"particle_id":600,"point":[4.693433058140866,0.08175508041299735,0.2141451693036449],"type":1,"volume":0.04149801448433661},{"fixed":false,"mass":0.03802965408149877,"nu":0,"particle_id":601,"point":[4.375402654026774,0.1394964252882641,0.154512430818948],"type":1,"volume":0.03802965408149877},{"fixed":false,"mass":0.030144360443739308,"nu":0,"particle_id":602,"point":[4.680056220420567,0.2432485237814724,-0.07181705251902776],"type":1,"volume":0.030144360443739308},{"fixed":false,"mass":0.050213124762800244,"nu":0,"particle_id":603,"point":[-4.230134159667958,0.2432398956110736,0.09742579262690607],"type":1,"volume":0.050213124762800244},{"fixed":false,"mass":0.041603213669708594,"nu":0,"particle_id":604,"point":[-3.786384831325708,-0.03161051763199596,0.2770216761074284],"type":1,"volume":0.041603213669708594},{"fixed":false,"mass":0.03637145118619197,"nu":0,"particle_id":605,"point":[-4.422167309558729,0.4103244327179061,-0.1361367443913499],"type":1,"volume":0.03637145118619197},{"fixed":false,"mass":0.06077608621634436,"nu":0,"particle_id":606,"point":[-4.591074029284952,0.5218767776194263,0.2376071322643191],"type":1,"volume":0.06077608621634436},{"fixed":false,"mass":0.010512229984721885,"nu":0,"particle_id":607,"point":[4.163826467824126,-0.1977277342956376,-0.9799852301349365],"type":1,"volume":0.010512229984721885},{"fixed":false,"mass":0.014528269654190766,"nu":0,"particle_id":608,"point":[4.340243541631816,0.07446050698183779,-0.9926662801726729],"type":1,"volume":0.014528269654190766},{"fixed":false,"mass":0.02278554460477448,"nu":0,"particle_id":609,"point":[4.488320570323084,-0.2059490210824351,-0.9774913300531761],"type":1,"volume":0.02278554460477448},{"fixed":false,"mass":0.02453134489198686,"nu":0,"particle_id":610,"point":[-2.507599831019654,-0.3251917085983898,-0.1662079725282857],"type":1,"volume":0.02453134489198686},{"fixed":false,"mass":0.04356856003183317,"nu":0,"particle_id":611,"point":[1.917682403638964,-0.6149249126684821,0.3408176604291094],"type":1,"volume":0.04356856003183317},{"fixed":false,"mass":0.009774985708728777,"nu":0,"particle_id":612,"point":[4.661116578349713,0.4732542658086731,-0.8754684134433468],"type":1,"volume":0.009774985708728777},{"fixed":false,"mass":0.013844227844929212,"nu":0,"particle_id":613,"point":[4.636397599014352,0.07446050698183776,-0.9926662801726729],"type":1,"volume":0.013844227844929212},{"fixed":false,"mass":0.014576045745633745,"nu":0,"particle_id":614,"point":[4.488320570323084,0.3481038288242587,-0.9343691405658545],"type":1,"volume":0.014576045745633745},{"fixed":false,"mass":0.019322392888852596,"nu":0,"particle_id":615,"point":[5,0.2218893377802671,-0.972655887847238],"type":2,"volume":0.019322392888852596},{"fixed":false,"mass":0.041259597506650224,"nu":0,"particle_id":616,"point":[-3.489121441165684,0.2149362391278992,0.325884387759761],"type":1,"volume":0.041259597506650224},{"fixed":false,"mass":0.04026606454124154,"nu":0,"particle_id":617,"point":[-1.138639015034695,-0.2400629374194092,-0.6285981132505296],"type":1,"volume":0.04026606454124154},{"fixed":false,"mass":0.031628791847108526,"nu":0,"particle_id":618,"point":[-0.7274905157977027,-0.2876802307984562,-0.9526984386386049],"type":1,"volume":0.031628791847108526},{"fixed":false,"mass":0.04829496485363478,"nu":0,"particle_id":619,"point":[-4.574654519941896,0.417022827851877,0.5530601972738634],"type":1,"volume":0.04829496485363478},{"fixed":false,"mass":0.02987053915501539,"nu":0,"particle_id":620,"point":[-4.382515799682801,0.1904781888959621,0.4029441553916916],"type":1,"volume":0.02987053915501539},{"fixed":false,"mass":0.044324440661677324,"nu":0,"particle_id":621,"point":[-3.163950808635486,-0.25019501132179,-0.1543223346026414],"type":1,"volume":0.044324440661677324},{"fixed":false,"mass":0.03689241100901186,"nu":0,"particle_id":622,"point":[-2.776663702363368,-0.1516075858922161,-0.2590825155128191],"type":1,"volume":0.03689241100901186},{"fixed":false,"mass":0.041830924309776196,"nu":0,"particle_id":623,"point":[0.7139411366369002,0.4337934095398617,0.4096115645500598],"type":1,"volume":0.041830924309776196},{"fixed":false,"mass":0.04737131124928005,"nu":0,"particle_id":624,"point":[0.4993683482456825,0.09093559815714725,0.4343931700264454],"type":1,"volume":0.04737131124928005},{"fixed":false,"mass":0.02218204117786233,"nu":0,"particle_id":625,"point":[0.7703021905336846,0.4516214175091813,-0.8870314117617619],"type":1,"volume":0.02218204117786233},{"fixed":false,"mass":0.04628013741426055,"nu":0,"particle_id":626,"point":[0.9018249559967544,0.5065005043303028,-0.4118695134071381],"type":1,"volume":0.04628013741426055},{"fixed":false,"mass":0.017886730269221232,"nu":0,"particle_id":627,"point":[-1.535528438334839,-0.9908729100065403,0.0926688998466358],"type":1,"volume":0.017886730269221232},{"fixed":false,"mass":0.053657698569364996,"nu":0,"particle_id":628,"point":[-2.187442448585294,-0.08206022356302697,0.2557157558819413],"type":1,"volume":0.053657698569364996},{"fixed":false,"mass":0.04555928662676743,"nu":0,"particle_id":629,"point":[-2.350424864374347,-0.02787779194807721,0.6775722205212122],"type":1,"volume":0.04555928662676743},{"fixed":false,"mass":0.032870788262845174,"nu":0,"particle_id":630,"point":[-4.327395754995817,0.5542229489225674,-0.4413914844169145],"type":1,"volume":0.032870788262845174},{"fixed":false,"mass":0.04595313913442981,"nu":0,"particle_id":631,"point":[-2.366237732649466,-0.3884288724081464,0.1317294800938162],"type":1,"volume":0.04595313913442981},{"fixed":false,"mass":0.01285187382762814,"nu":0,"particle_id":632,"point":[-3.676576209516508,0.9741655056931362,0.2169127946780121],"type":1,"volume":0.01285187382762814},{"fixed":false,"mass":0.011798851176050111,"nu":0,"particle_id":633,"point":[1.808962312949893,-0.372435126327165,-0.9269883221604844],"type":1,"volume":0.011798851176050111},{"fixed":false,"mass":0.04954398359532222,"nu":0,"particle_id":634,"point":[4.351280776835397,-0.1986246455689966,0.3063166437259053],"type":1,"volume":0.04954398359532222},{"fixed":false,"mass":0.03924772413403381,"nu":0,"particle_id":635,"point":[4.706614010279496,-0.323221534812599,0.2189115852253334],"type":1,"volume":0.03924772413403381},{"fixed":false,"mass":0.012999292833214101,"nu":0,"particle_id":636,"point":[-3.448230227189143,0.7665350668792379,-0.6346932055503549],"type":1,"volume":0.012999292833214101},{"fixed":false,"mass":0.043421267777213224,"nu":0,"particle_id":637,"point":[-3.32690593094136,0.5796975299350845,-0.344776763038902],"type":1,"volume":0.043421267777213224},{"fixed":false,"mass":0.05202202414396951,"nu":0,"particle_id":638,"point":[-1.375319693455053,-0.6754114424022399,0.1304388941651848],"type":1,"volume":0.05202202414396951},{"fixed":false,"mass":0.0192137239779568,"nu":0,"particle_id":639,"point":[-1.104678421744081,-0.8743530487629456,0.4753409663568618],"type":1,"volume":0.0192137239779568},{"fixed":false,"mass":0.024801767545802128,"nu":0,"particle_id":640,"point":[-1.444442000288382,-0.8580233842039799,0.505891619955344],"type":1,"volume":0.024801767545802128},{"fixed":false,"mass":0.03296713600843691,"nu":0,"particle_id":641,"point":[0.2925726381858547,0.7657902314599236,-0.635600790134772],"type":1,"volume":0.03296713600843691},{"fixed":false,"mass":0.03798097929396134,"nu":0,"particle_id":642,"point":[0.009619895223895725,0.6770546748216081,-0.2455305922343799],"type":1,"volume":0.03798097929396134},{"fixed":false,"mass":0.048060389000985256,"nu":0,"particle_id":643,"point":[0.3254521579048236,0.5566800084474709,-0.1797804490234932],"type":1,"volume":0.048060389000985256},{"fixed":false,"mass":0.01371732505911216,"nu":0,"particle_id":644,"point":[0.232379782904118,0.9352122732560246,-0.3453243928332544],"type":1,"volume":0.01371732505911216},{"fixed":false,"mass":0.06188534976812822,"nu":0,"particle_id":645,"point":[1.444535561271253,-0.5841122764054454,-0.242085071064743],"type":1,"volume":0.06188534976812822},{"fixed":false,"mass":0.04646052595929616,"nu":0,"particle_id":646,"point":[-1.271471914264679,0.01761256226764862,-0.4619636548207142],"type":1,"volume":0.04646052595929616},{"fixed":false,"mass":0.049680685651901445,"nu":0,"particle_id":647,"point":[-1.410904295863361,-0.3680358504838481,-0.48264320456259],"type":1,"volume":0.049680685651901445},{"fixed":false,"mass":0.02752102682693328,"nu":0,"particle_id":648,"point":[4.735227128363738,-0.5247402456935325,0.5221319116496578],"type":1,"volume":0.02752102682693328},{"fixed":false,"mass":0.05887868504840855,"nu":0,"particle_id":649,"point":[-3.157381738710829,0.4970662096673659,0.02974889135209569],"type":1,"volume":0.05887868504840855},{"fixed":false,"mass":0.007955771860268884,"nu":0,"particle_id":650,"point":[-5,-0.6998907550833564,-0.7130288207635025],"type":3,"volume":0.007955771860268884},{"fixed":false,"mass":0.014130863156838078,"nu":0,"particle_id":651,"point":[-4.624974620815479,-0.5846438277965926,-0.8076095296959223],"type":1,"volume":0.014130863156838078},{"fixed":false,"mass":0.019855800600684367,"nu":0,"particle_id":652,"point":[4.580847897476351,0.9509856974164264,0.2933263819342146],"type":1,"volume":0.019855800600684367},{"fixed":false,"mass":0.011407730604788186,"nu":0,"particle_id":653,"point":[4.646906927419687,0.8254937487210293,0.5628518438621122],"type":1,"volume":0.011407730604788186},{"fixed":false,"mass":0.041904385326682225,"nu":0,"particle_id":654,"point":[-4.253414912700126,0.6614060015357069,0.06730208274914794],"type":1,"volume":0.041904385326682225},{"fixed":false,"mass":0.04530941301665895,"nu":0,"particle_id":655,"point":[-3.671427197769818,0.518440633269609,0.4723880858931614],"type":1,"volume":0.04530941301665895},{"fixed":false,"mass":0.04494583093656096,"nu":0,"particle_id":656,"point":[-4.048503790611586,-0.5043556453840086,-0.1255254716413129],"type":1,"volume":0.04494583093656096},{"fixed":false,"mass":0.030969101464607983,"nu":0,"particle_id":657,"point":[-3.913677606210549,-0.8817981480559942,-0.4614121652668616],"type":1,"volume":0.030969101464607983},{"fixed":false,"mass":0.03285116441964949,"nu":0,"particle_id":658,"point":[-0.6629633491991008,-0.698062101859113,0.08412102544300182],"type":1,"volume":0.03285116441964949},{"fixed":false,"mass":0.04713138349586757,"nu":0,"particle_id":659,"point":[-0.4570722635997052,-0.387538138885484,-0.1307081317378684],"type":1,"volume":0.04713138349586757},{"fixed":false,"mass":0.024532505378535727,"nu":0,"particle_id":660,"point":[-0.3023490536143678,-0.9762217909957516,-0.2101341304837565],"type":1,"volume":0.024532505378535727},{"fixed":false,"mass":0.01554549554575124,"nu":0,"particle_id":661,"point":[-0.1087242510112853,-0.9982428491656505,0.01784065181788009],"type":1,"volume":0.01554549554575124},{"fixed":false,"mass":0.0192453821388684,"nu":0,"particle_id":662,"point":[-0.4025397659832879,0.2067089095731048,0.97726082039962],"type":1,"volume":0.0192453821388684},{"fixed":false,"mass":0.02607544110295224,"nu":0,"particle_id":663,"point":[-0.7720760308486068,0.1134674706120265,0.9888244295840336],"type":1,"volume":0.02607544110295224},{"fixed":false,"mass":0.009212662006952617,"nu":0,"particle_id":664,"point":[-2.228642004515327,0.01595616123011648,0.9984284552882521],"type":1,"volume":0.009212662006952617},{"fixed":false,"mass":0.02356912010930522,"nu":0,"particle_id":665,"point":[-2.095516302837346,-0.2828061764611767,0.9541769668575406],"type":1,"volume":0.02356912010930522},{"fixed":false,"mass":0.021264512399125017,"nu":0,"particle_id":666,"point":[-1.931132976067855,0.01417055134752818,0.9986043225114375],"type":1,"volume":0.021264512399125017},{"fixed":false,"mass":0.018235558772434782,"nu":0,"particle_id":667,"point":[4.527668614944568,0.6205798941161946,-0.7781175622416132],"type":1,"volume":0.018235558772434782},{"fixed":false,"mass":0.012036327436302247,"nu":0,"particle_id":668,"point":[4.402018392985044,-0.8973570037352268,0.4323035936530157],"type":1,"volume":0.012036327436302247},{"fixed":false,"mass":0.015665080742757517,"nu":0,"particle_id":669,"point":[4.253148278507963,-0.7388009391073256,0.6684873380195371],"type":1,"volume":0.015665080742757517},{"fixed":false,"mass":0.054293539841167845,"nu":0,"particle_id":670,"point":[4.159819484280419,-0.5494065708719695,0.2304299828395665],"type":1,"volume":0.054293539841167845},{"fixed":false,"mass":0.016841808653854918,"nu":0,"particle_id":671,"point":[0.06420236751527389,-0.8166348062959867,-0.5736464964400074],"type":1,"volume":0.016841808653854918},{"fixed":false,"mass":0.022804465229193053,"nu":0,"particle_id":672,"point":[4.135446613322827,0.5313565633892385,-0.8444120883622082],"type":1,"volume":0.022804465229193053},{"fixed":false,"mass":0.038293851415362366,"nu":0,"particle_id":673,"point":[-0.925804355909934,-0.004518178626906955,0.0004785107118250032],"type":1,"volume":0.038293851415362366},{"fixed":false,"mass":0.015283951025091743,"nu":0,"particle_id":674,"point":[-0.8058002516302656,0.4838323941568299,-0.8698142860437397],"type":1,"volume":0.015283951025091743},{"fixed":false,"mass":0.02764721205836933,"nu":0,"particle_id":675,"point":[4.537053949052114,-0.4977671297229341,-0.8623660147071284],"type":1,"volume":0.02764721205836933},{"fixed":false,"mass":0.042666350593617654,"nu":0,"particle_id":676,"point":[4.744240883412082,-0.113931699671622,-0.6524214811341036],"type":1,"volume":0.042666350593617654},{"fixed":false,"mass":0.05777409935713454,"nu":0,"particle_id":677,"point":[-0.8789689135833791,-0.1845625576951531,0.4876599776048535],"type":1,"volume":0.05777409935713454},{"fixed":false,"mass":0.05853359077289568,"nu":0,"particle_id":678,"point":[0.3651332029664986,-0.3601009101974055,0.4105952576288049],"type":1,"volume":0.05853359077289568},{"fixed":false,"mass":0.066511046502814,"nu":0,"particle_id":679,"point":[0.7293715009207702,-0.3144052243746575,0.1151943210496538],"type":1,"volume":0.066511046502814},{"fixed":false,"mass":0.02831411823801933,"nu":0,"particle_id":680,"point":[-0.06956324406863876,0.4828652465812916,0.02756949234738948],"type":1,"volume":0.02831411823801933},{"fixed":false,"mass":0.04547883426501539,"nu":0,"particle_id":681,"point":[-0.08140537661459862,0.2071479515692004,-0.184640419025046],"type":1,"volume":0.04547883426501539},{"fixed":false,"mass":0.053375916224962405,"nu":0,"particle_id":682,"point":[1.721306264450047,0.04066325406646043,0.07333831184449634],"type":1,"volume":0.053375916224962405},{"fixed":false,"mass":0.014287732399183467,"nu":0,"particle_id":683,"point":[-3.655263314690012,-0.9531037493793262,-0.2863441003489614],"type":1,"volume":0.014287732399183467},{"fixed":false,"mass":0.04618251547544299,"nu":0,"particle_id":684,"point":[-3.397621449765101,-0.2695303824920767,-0.6288409866573574],"type":1,"volume":0.04618251547544299},{"fixed":false,"mass":0.0442368433920273,"nu":0,"particle_id":685,"point":[-3.114668595186604,-0.4040995087402937,-0.4625285815680523],"type":1,"volume":0.0442368433920273},{"fixed":false,"mass":0.03206271363914593,"nu":0,"particle_id":686,"point":[-2.964870586279729,-0.2652805292784798,-0.7084884365829499],"type":1,"volume":0.03206271363914593},{"fixed":false,"mass":0.0377434373426539,"nu":0,"particle_id":687,"point":[-2.746029144278229,0.23274152375697,0.1388181166950751],"type":1,"volume":0.0377434373426539},{"fixed":false,"mass":0.05497247418447424,"nu":0,"particle_id":688,"point":[0.9609786967151244,-0.6318375059483623,0.0130832338571793],"type":1,"volume":0.05497247418447424},{"fixed":false,"mass":0.021083472296708903,"nu":0,"particle_id":689,"point":[1.076485150719801,-0.9665677104480226,-0.2419593689631238],"type":1,"volume":0.021083472296708903},{"fixed":false,"mass":0.016716234041704737,"nu":0,"particle_id":690,"point":[-2.625852263264195,0.005913611341259709,-0.9994175601200905],"type":1,"volume":0.016716234041704737},{"fixed":false,"mass":0.01752029411356024,"nu":0,"particle_id":691,"point":[-2.673210761504533,0.4938627594031302,-0.8644529441219393],"type":1,"volume":0.01752029411356024},{"fixed":false,"mass":0.010316047804215992,"nu":0,"particle_id":692,"point":[-2.392813984794203,0.2327979585973867,-0.9693467938996347],"type":1,"volume":0.010316047804215992},{"fixed":false,"mass":0.0445215318847589,"nu":0,"particle_id":693,"point":[3.227536686410194,0.2414455193098374,0.6237660249109391],"type":1,"volume":0.0445215318847589},{"fixed":false,"mass":0.06166101762898608,"nu":0,"particle_id":694,"point":[3.531540547810903,0.3414899535110812,0.3980129684537043],"type":1,"volume":0.06166101762898608},{"fixed":false,"mass":0.042261109507372996,"nu":0,"particle_id":695,"point":[3.791229862212546,0.3032824199607939,0.07845746443107662],"type":1,"volume":0.042261109507372996},{"fixed":false,"mass":0.015116823748407275,"nu":0,"particle_id":696,"point":[3.446416206872865,-0.9941494663090458,0.05940146542270348],"type":1,"volume":0.015116823748407275},{"fixed":false,"mass":0.02835544138151542,"nu":0,"particle_id":697,"point":[1.760624606010169,-0.3179696947472905,0.9435102302014818],"type":1,"volume":0.02835544138151542},{"fixed":false,"mass":0.043966790627099885,"nu":0,"particle_id":698,"point":[1.270265987270252,-0.2528995293844085,0.6205035974268185],"type":1,"volume":0.043966790627099885},{"fixed":false,"mass":0.02006348236481193,"nu":0,"particle_id":699,"point":[1.420489493381388,-0.4826950330226969,0.8704222182355322],"type":1,"volume":0.02006348236481193},{"fixed":false,"mass":0.021660024713002275,"nu":0,"particle_id":700,"point":[1.135671249496635,-0.9920701723240648,0.08051289153814563],"type":1,"volume":0.021660024713002275},{"fixed":false,"mass":0.028203884129266936,"nu":0,"particle_id":701,"point":[1.121201284298835,-0.9115789675157483,0.4056961708624052],"type":1,"volume":0.028203884129266936},{"fixed":false,"mass":0.025905786290736237,"nu":0,"particle_id":702,"point":[-0.7966426182374682,-0.5940829322323882,0.799863056881048],"type":1,"volume":0.025905786290736237},{"fixed":false,"mass":0.06351593929124241,"nu":0,"particle_id":703,"point":[-4.59695996521951,-0.5463100749002197,-0.1563790564372102],"type":1,"volume":0.06351593929124241},{"fixed":false,"mass":0.01761812562007996,"nu":0,"particle_id":704,"point":[-2.358410287233262,-0.9485341105152124,-0.3014081808583398],"type":1,"volume":0.01761812562007996},{"fixed":false,"mass":0.056521634213152545,"nu":0,"particle_id":705,"point":[-2.48178524376985,-0.6519872787805744,-0.1054563664001563],"type":1,"volume":0.056521634213152545},{"fixed":false,"mass":0.016813734565402017,"nu":0,"particle_id":706,"point":[-2.31712962705073,-0.9987034551074612,0.01316404120913029],"type":1,"volume":0.016813734565402017},{"fixed":false,"mass":0.021628118208947875,"nu":0,"particle_id":707,"point":[2.15179084138559,-0.5913269287547391,-0.8021248504826048],"type":1,"volume":0.021628118208947875},{"fixed":false,"mass":0.01345935118941953,"nu":0,"particle_id":708,"point":[1.942478671932009,-0.7342608432310473,-0.6740194608512897],"type":1,"volume":0.01345935118941953},{"fixed":false,"mass":0.008732624868600321,"nu":0,"particle_id":709,"point":[4.651659247048665,0.9999999999999998,1.138195324524555e-15],"type":1,"volume":0.008732624868600321},{"fixed":false,"mass":0.019003588144273477,"nu":0,"particle_id":710,"point":[-4.577237018905443,0.4568524196792358,0.8842353828496827],"type":1,"volume":0.019003588144273477},{"fixed":false,"mass":0.0438809229950362,"nu":0,"particle_id":711,"point":[3.162456851589179,-0.08365666246642264,0.7096093314211761],"type":1,"volume":0.0438809229950362},{"fixed":false,"mass":0.019137069467416213,"nu":0,"particle_id":712,"point":[3.290433060642117,-0.5427722305821285,0.8383102871233004],"type":1,"volume":0.019137069467416213},{"fixed":false,"mass":0.01627944135145098,"nu":0,"particle_id":713,"point":[3.418100172269944,-0.222100176157078,0.9725919307248567],"type":1,"volume":0.01627944135145098},{"fixed":false,"mass":0.03234343830275306,"nu":0,"particle_id":714,"point":[-3.911464790915464,-0.9979760723788782,-0.02054928198943779],"type":1,"volume":0.03234343830275306},{"fixed":false,"mass":0.019601745581188004,"nu":0,"particle_id":715,"point":[0.989604555372442,-0.7426898031901774,0.6637487434240508],"type":1,"volume":0.019601745581188004},{"fixed":false,"mass":0.04434607344161924,"nu":0,"particle_id":716,"point":[-0.1911299317791522,0.4536954592128478,-0.4817539055713745],"type":1,"volume":0.04434607344161924},{"fixed":false,"mass":0.015117173113744161,"nu":0,"particle_id":717,"point":[2.693966039161324,-0.5354653649731094,0.8422158881602178],"type":1,"volume":0.015117173113744161},{"fixed":false,"mass":0.007784944033246456,"nu":0,"particle_id":718,"point":[3.016780682442825,-0.560534530451235,0.8273955186890388],"type":1,"volume":0.007784944033246456},{"fixed":false,"mass":0.039632414107636064,"nu":0,"particle_id":719,"point":[2.893794313750116,-0.244772237738988,0.5711965468415355],"type":1,"volume":0.039632414107636064},{"fixed":false,"mass":0.020653173074459585,"nu":0,"particle_id":720,"point":[3.020624299478619,-0.3126521860584671,0.9451232788272895],"type":1,"volume":0.020653173074459585},{"fixed":false,"mass":0.02623085103993398,"nu":0,"particle_id":721,"point":[1.24071621592031,-0.8582495472868861,-0.5054684985876252],"type":1,"volume":0.02623085103993398},{"fixed":false,"mass":0.04965654399091817,"nu":0,"particle_id":722,"point":[-0.4605098609248872,-0.2184845285796867,-0.5622516634543868],"type":1,"volume":0.04965654399091817},{"fixed":false,"mass":0.009050216071417618,"nu":0,"particle_id":723,"point":[5,-0.8255475727255968,0.5627862591227855],"type":2,"volume":0.009050216071417618},{"fixed":false,"mass":0.01021102014231367,"nu":0,"particle_id":724,"point":[4.663840130288396,-0.8973570037352177,0.4323035936530126],"type":1,"volume":0.01021102014231367},{"fixed":false,"mass":0.008469080771082936,"nu":0,"particle_id":725,"point":[5,-0.9509775076979285,0.2933533798179586],"type":2,"volume":0.008469080771082936},{"fixed":false,"mass":0.02112387187115187,"nu":0,"particle_id":726,"point":[-3.103480325453528,0.710998768010813,-0.7023643815196381],"type":1,"volume":0.02112387187115187},{"fixed":false,"mass":0.03576306965719026,"nu":0,"particle_id":727,"point":[-2.277939546902767,-0.3486618938990526,0.5701262225403555],"type":1,"volume":0.03576306965719026},{"fixed":false,"mass":0.05570313004610678,"nu":0,"particle_id":728,"point":[-2.125932265609058,-0.5666218617516662,0.3293872056422673],"type":1,"volume":0.05570313004610678},{"fixed":false,"mass":0.020095269480922072,"nu":0,"particle_id":729,"point":[-1.824216603629308,0.08209446687597831,-0.9919144007495266],"type":1,"volume":0.020095269480922072},{"fixed":false,"mass":0.025860793346754632,"nu":0,"particle_id":730,"point":[-2.092558955727411,0.2801597126594034,-0.9549797628750955],"type":1,"volume":0.025860793346754632},{"fixed":false,"mass":0.022767332791566976,"nu":0,"particle_id":731,"point":[2.680685232607646,-0.9690587481371093,0.23374751822039],"type":1,"volume":0.022767332791566976},{"fixed":false,"mass":0.0274562182633043,"nu":0,"particle_id":732,"point":[-4.785969590544966,-0.6733459753643487,0.02615977644766874],"type":1,"volume":0.0274562182633043},{"fixed":false,"mass":0.019271165795968687,"nu":0,"particle_id":733,"point":[-4.57501567386343,-0.9298735369712038,-0.3629238477583372],"type":1,"volume":0.019271165795968687},{"fixed":false,"mass":0.03200083954975353,"nu":0,"particle_id":734,"point":[2.852092351235482,0.05627104666597491,0.9944577856454917],"type":1,"volume":0.03200083954975353},{"fixed":false,"mass":0.05912898379063926,"nu":0,"particle_id":735,"point":[-3.259542022845247,-0.5349896367138113,0.02134998157235843],"type":1,"volume":0.05912898379063926},{"fixed":false,"mass":0.0695441455844629,"nu":0,"particle_id":736,"point":[-4.203586046088312,-0.4955663907900864,-0.4515495288910022],"type":1,"volume":0.0695441455844629},{"fixed":false,"mass":0.04279890098558385,"nu":0,"particle_id":737,"point":[-4.256520154963077,-0.2316868155869173,-0.05965435350073278],"type":1,"volume":0.04279890098558385},{"fixed":false,"mass":0.0468369885274939,"nu":0,"particle_id":738,"point":[-3.767660199081937,-0.2666398609965951,-0.05485565286210847],"type":1,"volume":0.0468369885274939},{"fixed":false,"mass":0.02426499030593088,"nu":0,"particle_id":739,"point":[-3.325720822557405,-0.5846438277965949,-0.8076095296959205],"type":1,"volume":0.02426499030593088},{"fixed":false,"mass":0.018130133620084206,"nu":0,"particle_id":740,"point":[0.5733931729742487,0.904147066703071,-0.419600279332395],"type":1,"volume":0.018130133620084206},{"fixed":false,"mass":0.0658237214504222,"nu":0,"particle_id":741,"point":[0.5859797476043693,0.3488194704345844,-0.4410720707104369],"type":1,"volume":0.0658237214504222},{"fixed":false,"mass":0.016577555025124674,"nu":0,"particle_id":742,"point":[0.6658535560512417,0.7388053574815705,-0.6684819542149427],"type":1,"volume":0.016577555025124674},{"fixed":false,"mass":0.023825367635642577,"nu":0,"particle_id":743,"point":[4.556863234858207,-0.4977671297229385,0.8623660147071259],"type":1,"volume":0.023825367635642577},{"fixed":false,"mass":0.006215821098584831,"nu":0,"particle_id":744,"point":[5,-0.6205144679482972,0.7781712561099714],"type":2,"volume":0.006215821098584831},{"fixed":false,"mass":0.01741021535246159,"nu":0,"particle_id":745,"point":[5,0.3705782882363479,-0.4617902932827067],"type":2,"volume":0.01741021535246159},{"fixed":false,"mass":0.026046365278526756,"nu":0,"particle_id":746,"point":[-2.477255275584501,-0.3981460965541221,0.9156145663107814],"type":1,"volume":0.026046365278526756},{"fixed":false,"mass":0.0070767209045681685,"nu":0,"particle_id":747,"point":[0.2590834890717727,-0.7447241479705666,0.6612698871368841],"type":1,"volume":0.0070767209045681685},{"fixed":false,"mass":0.023422642472461883,"nu":0,"particle_id":748,"point":[0.2586867727489252,-0.5671089209906367,0.8220000558107274],"type":1,"volume":0.023422642472461883},{"fixed":false,"mass":0.011632210988823414,"nu":0,"particle_id":749,"point":[0.4932288421172942,-0.712641988240192,0.700362111876822],"type":1,"volume":0.011632210988823414},{"fixed":false,"mass":0.00974767425074466,"nu":0,"particle_id":750,"point":[-5,0.3201523955821015,0.9428481151419349],"type":3,"volume":0.00974767425074466},{"fixed":false,"mass":0.019726543663402357,"nu":0,"particle_id":751,"point":[-0.1877877425951968,-0.9361801382995315,0.3421337693789372],"type":1,"volume":0.019726543663402357},{"fixed":false,"mass":0.016194855397168403,"nu":0,"particle_id":752,"point":[-5,-0.02194905635951594,0.009491427548765974],"type":3,"volume":0.016194855397168403},{"fixed":false,"mass":0.019301457989369216,"nu":0,"particle_id":753,"point":[-5,0.2607148816636544,-0.02470847594036885],"type":3,"volume":0.019301457989369216},{"fixed":false,"mass":0.04599286913949686,"nu":0,"particle_id":754,"point":[3.9830492563974,0.1170449999288404,-0.2431364624687885],"type":1,"volume":0.04599286913949686},{"fixed":false,"mass":0.035103590600866846,"nu":0,"particle_id":755,"point":[-2.640703135364204,-0.09812191513921689,-0.6658512296991435],"type":1,"volume":0.035103590600866846},{"fixed":false,"mass":0.039917069243399654,"nu":0,"particle_id":756,"point":[0.5915303231559501,-0.6564890990073797,0.05885906579729908],"type":1,"volume":0.039917069243399654},{"fixed":false,"mass":0.05010788483142471,"nu":0,"particle_id":757,"point":[1.086737415971635,0.5860076402739114,-0.1203900270826509],"type":1,"volume":0.05010788483142471},{"fixed":false,"mass":0.014587918212517984,"nu":0,"particle_id":758,"point":[-1.214605500099896,0.2330549143663812,-0.9692688472192765],"type":1,"volume":0.014587918212517984},{"fixed":false,"mass":0.0207753339547525,"nu":0,"particle_id":759,"point":[-1.489595967843478,0.1070864285505619,-0.9894529073715486],"type":1,"volume":0.0207753339547525},{"fixed":false,"mass":0.03870175008191548,"nu":0,"particle_id":760,"point":[2.324497522541967,0.02329915440803595,-0.7128572065011474],"type":1,"volume":0.03870175008191548},{"fixed":false,"mass":0.029551568087968015,"nu":0,"particle_id":761,"point":[1.075248433600345,-0.2407625866530808,0.966930750392774],"type":1,"volume":0.029551568087968015},{"fixed":false,"mass":0.020705479512787128,"nu":0,"particle_id":762,"point":[3.513410472270683,0.3414646164806373,0.936383123612057],"type":1,"volume":0.020705479512787128},{"fixed":false,"mass":0.016280086777034623,"nu":0,"particle_id":763,"point":[3.492990668630723,0.6114945156414721,0.7855737396624688],"type":1,"volume":0.016280086777034623},{"fixed":false,"mass":0.03623205762978816,"nu":0,"particle_id":764,"point":[-4.003302870551722,0.0007608749557562189,0.00204800320250929],"type":1,"volume":0.03623205762978816},{"fixed":false,"mass":0.04701038759279535,"nu":0,"particle_id":765,"point":[-4.055683451346948,-0.188774891869352,0.4815650360858951],"type":1,"volume":0.04701038759279535},{"fixed":false,"mass":0.03830909498355915,"nu":0,"particle_id":766,"point":[-4.244694915732348,-0.06473154205031231,0.2322943648967957],"type":1,"volume":0.03830909498355915},{"fixed":false,"mass":0.06385659070157333,"nu":0,"particle_id":767,"point":[-4.091361842785781,-0.5393319919165178,0.2777603225657664],"type":1,"volume":0.06385659070157333},{"fixed":false,"mass":0.024173489463410677,"nu":0,"particle_id":768,"point":[2.220043793660867,-0.3763646622642715,0.9257963104658471],"type":1,"volume":0.024173489463410677},{"fixed":false,"mass":0.0490968068717543,"nu":0,"particle_id":769,"point":[2.544774362300753,-0.2776724166634312,0.6556272919154937],"type":1,"volume":0.0490968068717543},{"fixed":false,"mass":0.012697781256393838,"nu":0,"particle_id":770,"point":[-5,0.4073815467443078,-0.9106781153386083],"type":3,"volume":0.012697781256393838},{"fixed":false,"mass":0.052585490146261835,"nu":0,"particle_id":771,"point":[3.502109060749879,0.5711175641972807,-0.3095446411600226],"type":1,"volume":0.052585490146261835},{"fixed":false,"mass":0.016735142609989984,"nu":0,"particle_id":772,"point":[3.226494421798939,0.1024221451079542,0.9899122991934665],"type":1,"volume":0.016735142609989984},{"fixed":false,"mass":0.01390415732930089,"nu":0,"particle_id":773,"point":[1.453857954698241,-0.5774988543781401,-0.813473257841481],"type":1,"volume":0.01390415732930089},{"fixed":false,"mass":0.01530294321183761,"nu":0,"particle_id":774,"point":[0.256209010899544,0.5009621701354976,0.8606582300268001],"type":1,"volume":0.01530294321183761},{"fixed":false,"mass":0.01855084268985284,"nu":0,"particle_id":775,"point":[-4.075596602671359,0.7229906538958051,0.6877522262903268],"type":1,"volume":0.01855084268985284},{"fixed":false,"mass":0.03179839848979382,"nu":0,"particle_id":776,"point":[-4.281928690919859,0.53073895025119,0.4117426766153431],"type":1,"volume":0.03179839848979382},{"fixed":false,"mass":0.01595260610920712,"nu":0,"particle_id":777,"point":[-4.188308908225315,0.877110250902642,0.4701826039687858],"type":1,"volume":0.01595260610920712},{"fixed":false,"mass":0.013113198798782949,"nu":0,"particle_id":778,"point":[-4.555990556609528,-0.6564419374057988,0.7486863439180553],"type":1,"volume":0.013113198798782949},{"fixed":false,"mass":0.04192611840109016,"nu":0,"particle_id":779,"point":[-4.334146975282854,-0.4104455021813264,0.5446612585311107],"type":1,"volume":0.04192611840109016},{"fixed":false,"mass":0.02521401235283282,"nu":0,"particle_id":780,"point":[-4.165267002179339,-0.6564419374057989,0.7486863439180553],"type":1,"volume":0.02521401235283282},{"fixed":false,"mass":0.009538295062898657,"nu":0,"particle_id":781,"point":[4.628626286996941,-0.7309668637931759,0.6780331864095501],"type":1,"volume":0.009538295062898657},{"fixed":false,"mass":0.009917756762908521,"nu":0,"particle_id":782,"point":[4.596282613920263,-0.9828092080243529,0.1745410400266877],"type":1,"volume":0.009917756762908521},{"fixed":false,"mass":0.03169655195659053,"nu":0,"particle_id":783,"point":[4.575169188762191,-0.9828092080243529,-0.1745410400266891],"type":1,"volume":0.03169655195659053},{"fixed":false,"mass":0.02904667974913953,"nu":0,"particle_id":784,"point":[-4.12318954898115,-0.319963410395838,-0.942905443171439],"type":1,"volume":0.02904667974913953},{"fixed":false,"mass":0.016080490818060518,"nu":0,"particle_id":785,"point":[-3.862629353307292,0.02778959530283349,-0.9972629637598964],"type":1,"volume":0.016080490818060518},{"fixed":false,"mass":0.03565907143878796,"nu":0,"particle_id":786,"point":[-3.697629259143497,-0.1814585211842585,-0.70247282031566],"type":1,"volume":0.03565907143878796},{"fixed":false,"mass":0.0449862962422117,"nu":0,"particle_id":787,"point":[3.655620038152969,-0.4760945690381373,0.484409348778537],"type":1,"volume":0.0449862962422117},{"fixed":false,"mass":0.017612863195744247,"nu":0,"particle_id":788,"point":[-4.121247670649532,-0.6159340426210336,-0.781930314029031],"type":1,"volume":0.017612863195744247},{"fixed":false,"mass":0.018003852265482307,"nu":0,"particle_id":789,"point":[-3.78529660158711,-0.5961918727628399,-0.7981322941165876],"type":1,"volume":0.018003852265482307},{"fixed":false,"mass":0.020299400312818655,"nu":0,"particle_id":790,"point":[-1.92856581210051,-0.6848282193745908,-0.7253903243557858],"type":1,"volume":0.020299400312818655},{"fixed":false,"mass":0.038496112712237,"nu":0,"particle_id":791,"point":[-3.491983949902207,-0.2518959286380135,-0.2873505353339552],"type":1,"volume":0.038496112712237},{"fixed":false,"mass":0.019302703553633952,"nu":0,"particle_id":792,"point":[5,0.2948672572053729,0.3659930539337671],"type":2,"volume":0.019302703553633952},{"fixed":false,"mass":0.011497013718417822,"nu":0,"particle_id":793,"point":[-1.817909920598321,0.4000230401755194,-0.9146113190435923],"type":1,"volume":0.011497013718417822},{"fixed":false,"mass":0.013675916571746854,"nu":0,"particle_id":794,"point":[-4.58084524739289,0.9899379122074039,-0.1021620918133077],"type":1,"volume":0.013675916571746854},{"fixed":false,"mass":0.037413255796241836,"nu":0,"particle_id":795,"point":[-4.697874729556153,0.7229412841159919,0.01893974149319015],"type":1,"volume":0.037413255796241836},{"fixed":false,"mass":0.020332608497828274,"nu":0,"particle_id":796,"point":[-4.374136593308616,0.9807852804032298,0.1950903220161303],"type":1,"volume":0.020332608497828274},{"fixed":false,"mass":0.01952678434740736,"nu":0,"particle_id":797,"point":[2.738697447309816,-0.7337335150551711,-0.6746620120927369],"type":1,"volume":0.01952678434740736},{"fixed":false,"mass":0.015127647529468186,"nu":0,"particle_id":798,"point":[3.034958788831322,-0.8108888957501768,-0.58064790869779],"type":1,"volume":0.015127647529468186},{"fixed":false,"mass":0.01562086361559946,"nu":0,"particle_id":799,"point":[2.892983558139663,-0.5162743990345224,-0.8524736731640439],"type":1,"volume":0.01562086361559946},{"fixed":false,"mass":0.03050647423898588,"nu":0,"particle_id":800,"point":[2.866927321559395,-0.6094732371651493,-0.3853964917095188],"type":1,"volume":0.03050647423898588},{"fixed":false,"mass":0.013090310443179997,"nu":0,"particle_id":801,"point":[-5,-0.9194790601203947,0.3909161371581612],"type":3,"volume":0.013090310443179997},{"fixed":false,"mass":0.02631116772221521,"nu":0,"particle_id":802,"point":[-1.558907941159893,0.5308945188922446,0.8446590562911562],"type":1,"volume":0.02631116772221521},{"fixed":false,"mass":0.013993073534030271,"nu":0,"particle_id":803,"point":[1.969620072172437,0.01500244206780216,-0.9985223884269576],"type":1,"volume":0.013993073534030271},{"fixed":false,"mass":0.0201474987358745,"nu":0,"particle_id":804,"point":[3.946617208917687,-0.7993972913085472,0.5946504692245781],"type":1,"volume":0.0201474987358745},{"fixed":false,"mass":0.020094895248627398,"nu":0,"particle_id":805,"point":[-3.894467368939464,0.9984241346247207,-0.01600002966314398],"type":1,"volume":0.020094895248627398},{"fixed":false,"mass":0.03922739405685095,"nu":0,"particle_id":806,"point":[-1.435341336616564,-0.01284393111281267,0.4082116907052072],"type":1,"volume":0.03922739405685095},{"fixed":false,"mass":0.012290381395306865,"nu":0,"particle_id":807,"point":[0.643900004609198,-0.8668404512045444,0.4893960478193609],"type":1,"volume":0.012290381395306865},{"fixed":false,"mass":0.014514420894431786,"nu":0,"particle_id":808,"point":[-3.559412831844858,0.990543017157963,-0.09601835814789468],"type":1,"volume":0.014514420894431786},{"fixed":false,"mass":0.021275019131801767,"nu":0,"particle_id":809,"point":[2.898449202692757,0.09205556262774353,-0.9909333184499602],"type":1,"volume":0.021275019131801767},{"fixed":false,"mass":0.03346719578763471,"nu":0,"particle_id":810,"point":[4.22662738303064,-0.3191689821825426,-0.5974749040944758],"type":1,"volume":0.03346719578763471},{"fixed":false,"mass":0.01662373190053668,"nu":0,"particle_id":811,"point":[-5,0.9374285201046061,0.3380184060915296],"type":3,"volume":0.01662373190053668},{"fixed":false,"mass":0.013011762229091658,"nu":0,"particle_id":812,"point":[-5,0.7959373748408309,0.5988663896387303],"type":3,"volume":0.013011762229091658},{"fixed":false,"mass":0.019345526770172202,"nu":0,"particle_id":813,"point":[-4.58084524739289,0.8754876355926597,0.4732183036967173],"type":1,"volume":0.019345526770172202},{"fixed":false,"mass":0.014815123966495005,"nu":0,"particle_id":814,"point":[-2.03281933427589,-0.8362293125187303,0.5466654602355543],"type":1,"volume":0.014815123966495005},{"fixed":false,"mass":0.036947354115734604,"nu":0,"particle_id":815,"point":[4.175407123636684,-0.6582773800494885,-0.08516772705858519],"type":1,"volume":0.036947354115734604},{"fixed":false,"mass":0.007446383099660169,"nu":0,"particle_id":816,"point":[4.199225869966604,-0.9916395398294391,-0.0848851766305172],"type":1,"volume":0.007446383099660169},{"fixed":false,"mass":0.013185652121470054,"nu":0,"particle_id":817,"point":[4.34015412990535,-0.8973570037352149,-0.4323035936530183],"type":1,"volume":0.013185652121470054},{"fixed":false,"mass":0.01491166149165613,"nu":0,"particle_id":818,"point":[-2.904128987013562,0.06165625224470335,-0.9939273891906759],"type":1,"volume":0.01491166149165613},{"fixed":false,"mass":0.013955282277620622,"nu":0,"particle_id":819,"point":[2.497323416623495,0.5361354073337034,-0.8418577430569207],"type":1,"volume":0.013955282277620622},{"fixed":false,"mass":0.04898774337717699,"nu":0,"particle_id":820,"point":[-1.76505612723359,0.3697171384924154,0.3796066055044007],"type":1,"volume":0.04898774337717699},{"fixed":false,"mass":0.04454944396515345,"nu":0,"particle_id":821,"point":[-0.5644856060732086,-0.4583832890792475,0.3056824200135005],"type":1,"volume":0.04454944396515345},{"fixed":false,"mass":0.018722881220347157,"nu":0,"particle_id":822,"point":[-5,-0.4686214856700356,-0.3595028107137161],"type":3,"volume":0.018722881220347157},{"fixed":false,"mass":0.013998868752778433,"nu":0,"particle_id":823,"point":[-5,-0.9807852804032304,-0.1950903220161282],"type":3,"volume":0.013998868752778433},{"fixed":false,"mass":0.01721389347247809,"nu":0,"particle_id":824,"point":[3.03725880926227,-0.9511585932163743,-0.2927564208656069],"type":1,"volume":0.01721389347247809},{"fixed":false,"mass":0.022467796987973035,"nu":0,"particle_id":825,"point":[3.882918686749066,-0.2799989074428845,-0.9550285426042333],"type":1,"volume":0.022467796987973035},{"fixed":false,"mass":0.010263179752784981,"nu":0,"particle_id":826,"point":[3.607092490457497,0.03846000412448825,0.9962120202206568],"type":1,"volume":0.010263179752784981},{"fixed":false,"mass":0.007406331910879846,"nu":0,"particle_id":827,"point":[3.854120641958811,0.1938815714248295,0.9809043319452762],"type":1,"volume":0.007406331910879846},{"fixed":false,"mass":0.05902785065158163,"nu":0,"particle_id":828,"point":[3.819205945894908,0.1931039288906354,0.6006340772910255],"type":1,"volume":0.05902785065158163},{"fixed":false,"mass":0.01725582004785352,"nu":0,"particle_id":829,"point":[-2.638278484060216,0.5270761876683603,0.8466999968510709],"type":1,"volume":0.01725582004785352},{"fixed":false,"mass":0.005248405779357761,"nu":0,"particle_id":830,"point":[-4.700376131771309,0.5389652345127411,-0.8403451689169088],"type":1,"volume":0.005248405779357761},{"fixed":false,"mass":0.016812048295838693,"nu":0,"particle_id":831,"point":[2.501885029966194,-0.5263717930434294,-0.8470765036222003],"type":1,"volume":0.016812048295838693},{"fixed":false,"mass":0.04286497673874116,"nu":0,"particle_id":832,"point":[4.065597221477949,0.3112195992560938,0.2801213078028672],"type":1,"volume":0.04286497673874116},{"fixed":false,"mass":0.02837434048394912,"nu":0,"particle_id":833,"point":[1.017141173423075,0.1305377899294842,-0.9871431498787024],"type":1,"volume":0.02837434048394912},{"fixed":false,"mass":0.0158565095773368,"nu":0,"particle_id":834,"point":[5,0.2712872660223193,0.08321216776031559],"type":2,"volume":0.0158565095773368},{"fixed":false,"mass":0.009419481611833955,"nu":0,"particle_id":835,"point":[-4.651655689130825,0.9807852804032298,0.1950903220161303],"type":1,"volume":0.009419481611833955},{"fixed":false,"mass":0.018443206010338373,"nu":0,"particle_id":836,"point":[-0.8031032684701176,-0.9707535534354219,0.2281604939016847],"type":1,"volume":0.018443206010338373},{"fixed":false,"mass":0.02027613119084177,"nu":0,"particle_id":837,"point":[1.262267296448422,0.9580817586416335,-0.2699338030511317],"type":1,"volume":0.02027613119084177},{"fixed":false,"mass":0.028141821775393157,"nu":0,"particle_id":838,"point":[1.293651981452946,0.7310782402631218,-0.6778974737882539],"type":1,"volume":0.028141821775393157},{"fixed":false,"mass":0.0075897394738910955,"nu":0,"particle_id":839,"point":[1.36974854875998,0.5388161648680234,-0.8404248483020427],"type":1,"volume":0.0075897394738910955},{"fixed":false,"mass":0.021374422102044578,"nu":0,"particle_id":840,"point":[4.189074664752528,0.9519411477932254,0.2901766841513459],"type":1,"volume":0.021374422102044578},{"fixed":false,"mass":0.013233285206053871,"nu":0,"particle_id":841,"point":[4.07668894826651,0.8434329335823109,0.5331884331372012],"type":1,"volume":0.013233285206053871},{"fixed":false,"mass":0.012902547585083001,"nu":0,"particle_id":842,"point":[5,-0.4833066695067952,0.4422761036295141],"type":2,"volume":0.012902547585083001},{"fixed":false,"mass":0.012343483213434625,"nu":0,"particle_id":843,"point":[0.727062545857337,-0.207079546841794,0.9771483888133419],"type":1,"volume":0.012343483213434625},{"fixed":false,"mass":0.015482192467032757,"nu":0,"particle_id":844,"point":[0.9957649693179921,-0.5099445397569482,0.8558570534369088],"type":1,"volume":0.015482192467032757},{"fixed":false,"mass":0.01959246860361251,"nu":0,"particle_id":845,"point":[-0.8975422127263668,-0.6608012458279237,-0.7451087519533367],"type":1,"volume":0.01959246860361251},{"fixed":false,"mass":0.013538372376151577,"nu":0,"particle_id":846,"point":[-1.590397062036574,-0.01883960355718587,0.9981444610069601],"type":1,"volume":0.013538372376151577},{"fixed":false,"mass":0.020767270134644945,"nu":0,"particle_id":847,"point":[3.32939208073347,-0.7309668637931708,-0.678033186409555],"type":1,"volume":0.020767270134644945},{"fixed":false,"mass":0.011191740042498243,"nu":0,"particle_id":848,"point":[3.452301998944413,-0.5254232857043446,-0.8475834913574724],"type":1,"volume":0.011191740042498243},{"fixed":false,"mass":0.045414556623350186,"nu":0,"particle_id":849,"point":[-1.081096756120432,0.3551715364913108,0.3360883481964242],"type":1,"volume":0.045414556623350186},{"fixed":false,"mass":0.017293193276352727,"nu":0,"particle_id":850,"point":[-0.5812257352390371,-0.2163072499423103,0.9743491956804871],"type":1,"volume":0.017293193276352727},{"fixed":false,"mass":0.037603696194073014,"nu":0,"particle_id":851,"point":[2.644548139484103,-0.3927657155120101,-0.2828718274028114],"type":1,"volume":0.037603696194073014},{"fixed":false,"mass":0.03978744088441872,"nu":0,"particle_id":852,"point":[2.658521506043542,-0.07621423898765414,-0.2234505574181146],"type":1,"volume":0.03978744088441872},{"fixed":false,"mass":0.0106268982577767,"nu":0,"particle_id":853,"point":[5,0.02646898453246005,0.3189956443125266],"type":2,"volume":0.0106268982577767},{"fixed":false,"mass":0.013713353459169362,"nu":0,"particle_id":854,"point":[3.773238805576417,0.3646659590504729,-0.9293450732882595],"type":1,"volume":0.013713353459169362},{"fixed":false,"mass":0.02360820135163886,"nu":0,"particle_id":855,"point":[0.9950934131828526,0.8563774796715395,0.5089708907539108],"type":1,"volume":0.02360820135163886},{"fixed":false,"mass":0.019486648044457735,"nu":0,"particle_id":856,"point":[0.88411807014029,0.5865227873318022,0.8060675074565504],"type":1,"volume":0.019486648044457735},{"fixed":false,"mass":0.012763282508467994,"nu":0,"particle_id":857,"point":[3.818366933684946,0.4623361672706512,0.8813042586953279],"type":1,"volume":0.012763282508467994},{"fixed":false,"mass":0.018931987093101885,"nu":0,"particle_id":858,"point":[-0.6460126253697802,0.8343841664851861,-0.550117485664851],"type":1,"volume":0.018931987093101885},{"fixed":false,"mass":0.018161190684423505,"nu":0,"particle_id":859,"point":[2.110380356184603,-0.8973570037352183,0.4323035936530122],"type":1,"volume":0.018161190684423505},{"fixed":false,"mass":0.05010517658841071,"nu":0,"particle_id":860,"point":[2.360893113207643,-0.5947028171352703,0.3999710556624263],"type":1,"volume":0.05010517658841071},{"fixed":false,"mass":0.023264814532171496,"nu":0,"particle_id":861,"point":[1.383589199207631,-0.8064454846182815,0.5860622208276414],"type":1,"volume":0.023264814532171496},{"fixed":false,"mass":0.014497213141698743,"nu":0,"particle_id":862,"point":[3.479599049134957,0.5705701506351553,-0.8191594980512836],"type":1,"volume":0.014497213141698743},{"fixed":false,"mass":0.012408852546405853,"nu":0,"particle_id":863,"point":[1.769285988296441,0.5161767369817982,0.8525258746187849],"type":1,"volume":0.012408852546405853},{"fixed":false,"mass":0.034592000627915474,"nu":0,"particle_id":864,"point":[1.771608700474546,0.481752322847868,0.4839176413632587],"type":1,"volume":0.034592000627915474},{"fixed":false,"mass":0.010651721681210891,"nu":0,"particle_id":865,"point":[-5,0.4885003967766002,0.4371610526780115],"type":3,"volume":0.010651721681210891},{"fixed":false,"mass":0.014833194805495735,"nu":0,"particle_id":866,"point":[-5,-0.3864359186248838,0.4470709954313534],"type":3,"volume":0.014833194805495735},{"fixed":false,"mass":0.01794567472906878,"nu":0,"particle_id":867,"point":[-5,-0.4773034020708162,-0.004523725118074558],"type":3,"volume":0.01794567472906878},{"fixed":false,"mass":0.04308640164938407,"nu":0,"particle_id":868,"point":[-1.426405862694348,-0.3878560180986912,-0.07281324780605901],"type":1,"volume":0.04308640164938407},{"fixed":false,"mass":0.026378546662816364,"nu":0,"particle_id":869,"point":[-2.731274653831263,0.8576608919516374,-0.5065697952597732],"type":1,"volume":0.026378546662816364},{"fixed":false,"mass":0.0070741496201421825,"nu":0,"particle_id":870,"point":[-5,-0.9899351468778825,0.1021901686751149],"type":3,"volume":0.0070741496201421825},{"fixed":false,"mass":0.018581905706613777,"nu":0,"particle_id":871,"point":[0.4713995813249322,0.9875081498519696,0.1268318830094318],"type":1,"volume":0.018581905706613777},{"fixed":false,"mass":0.06623392550933589,"nu":0,"particle_id":872,"point":[3.847102991334348,-0.1636705955856283,0.467371926458766],"type":1,"volume":0.06623392550933589},{"fixed":false,"mass":0.019588253947273235,"nu":0,"particle_id":873,"point":[0.7896638888172067,-0.9172572018855103,-0.3950729415452727],"type":1,"volume":0.019588253947273235},{"fixed":false,"mass":0.038908773110140474,"nu":0,"particle_id":874,"point":[-1.226829747770519,-0.1642705062822924,0.1433615889100902],"type":1,"volume":0.038908773110140474},{"fixed":false,"mass":0.03526648662081646,"nu":0,"particle_id":875,"point":[-4.720064496188005,-0.434945482037616,0.5697399135833435],"type":1,"volume":0.03526648662081646},{"fixed":false,"mass":0.012680080554107648,"nu":0,"particle_id":876,"point":[2.755808775921264,-0.9953549805220134,-0.04716167421376027],"type":1,"volume":0.012680080554107648},{"fixed":false,"mass":0.0072027454020024955,"nu":0,"particle_id":877,"point":[3.023494341624243,-0.9971668136219628,-0.02876582403606389],"type":1,"volume":0.0072027454020024955},{"fixed":false,"mass":0.014012705417763107,"nu":0,"particle_id":878,"point":[3.782929527686883,0.6962160491436713,0.7160445739907342],"type":1,"volume":0.014012705417763107},{"fixed":false,"mass":0.020516304172907767,"nu":0,"particle_id":879,"point":[-1.891106079300321,0.5453452477067415,0.836934980817202],"type":1,"volume":0.020516304172907767},{"fixed":false,"mass":0.041408742325363596,"nu":0,"particle_id":880,"point":[3.048088433835933,-0.05568346955649797,-0.3292773400576424],"type":1,"volume":0.041408742325363596},{"fixed":false,"mass":0.021391988707228065,"nu":0,"particle_id":881,"point":[0.008336871805605078,-0.6601232310681446,0.7456651842865538],"type":1,"volume":0.021391988707228065},{"fixed":false,"mass":0.014983601470775588,"nu":0,"particle_id":882,"point":[0.07599930308057459,-0.84278937191939,0.5343924523233983],"type":1,"volume":0.014983601470775588},{"fixed":false,"mass":0.02189420570375484,"nu":0,"particle_id":883,"point":[-1.372123272411018,-0.2496166080841051,-0.9642449123550845],"type":1,"volume":0.02189420570375484},{"fixed":false,"mass":0.019904632212475827,"nu":0,"particle_id":884,"point":[-1.032981313808654,-0.8420790047835215,-0.535721455758668],"type":1,"volume":0.019904632212475827},{"fixed":false,"mass":0.015815439853529747,"nu":0,"particle_id":885,"point":[-0.6021665887164753,-0.8744059767559906,-0.4752419450465744],"type":1,"volume":0.015815439853529747},{"fixed":false,"mass":0.01029179829843091,"nu":0,"particle_id":886,"point":[1.735460826894034,-0.8341046198297002,0.5506404806722207],"type":1,"volume":0.01029179829843091},{"fixed":false,"mass":0.0209262717349097,"nu":0,"particle_id":887,"point":[1.538350053799626,-0.9026780584977,0.4223486003804833],"type":1,"volume":0.0209262717349097},{"fixed":false,"mass":0.012516437978313918,"nu":0,"particle_id":888,"point":[2.478435503219927,0.9523860387624878,0.2887100751745417],"type":1,"volume":0.012516437978313918},{"fixed":false,"mass":0.021088704992721963,"nu":0,"particle_id":889,"point":[-3.30455601618833,0.9934259716528349,-0.0667472299417394],"type":1,"volume":0.021088704992721963},{"fixed":false,"mass":0.0172079693389394,"nu":0,"particle_id":890,"point":[-2.378431927216949,-0.7173683464688816,0.6946030277119722],"type":1,"volume":0.0172079693389394},{"fixed":false,"mass":0.016660192492417705,"nu":0,"particle_id":891,"point":[-0.4857359066954128,-0.9974165633826857,0.02623007216118839],"type":1,"volume":0.016660192492417705},{"fixed":false,"mass":0.014560748411540234,"nu":0,"particle_id":892,"point":[-2.097623578467058,0.3086850244080812,0.9463267041572685],"type":1,"volume":0.014560748411540234},{"fixed":false,"mass":0.01267607996295548,"nu":0,"particle_id":893,"point":[-3.214744532648337,-0.8398856871694207,-0.5398248643998951],"type":1,"volume":0.01267607996295548},{"fixed":false,"mass":0.022377622970051744,"nu":0,"particle_id":894,"point":[-1.812830046359739,-0.2520681666026048,-0.9635012402088283],"type":1,"volume":0.022377622970051744},{"fixed":false,"mass":0.01909228000998195,"nu":0,"particle_id":895,"point":[3.589271282503012,-0.2881055890537506,-0.9525694076225162],"type":1,"volume":0.01909228000998195},{"fixed":false,"mass":0.06093045971196903,"nu":0,"particle_id":896,"point":[3.373690414531628,-0.1764079259111183,-0.591523158755267],"type":1,"volume":0.06093045971196903},{"fixed":false,"mass":0.023449475561800208,"nu":0,"particle_id":897,"point":[-3.519368227026429,-0.8340798301519676,-0.5506868588972289],"type":1,"volume":0.023449475561800208},{"fixed":false,"mass":0.017805617195813455,"nu":0,"particle_id":898,"point":[3.537881526398872,0.8038592670669084,0.589213536031927],"type":1,"volume":0.017805617195813455},{"fixed":false,"mass":0.018987091955239108,"nu":0,"particle_id":899,"point":[-1.163341097459726,-0.5375675683470245,-0.841092237046826],"type":1,"volume":0.018987091955239108},{"fixed":false,"mass":0.009353736786114375,"nu":0,"particle_id":900,"point":[-3.841488815425527,-0.3528605276076728,-0.932926211764987],"type":1,"volume":0.009353736786114375},{"fixed":false,"mass":0.008954560169800868,"nu":0,"particle_id":901,"point":[-3.562544816325609,-0.401470932539006,-0.9138374044516511],"type":1,"volume":0.008954560169800868},{"fixed":false,"mass":0.007114702339142866,"nu":0,"particle_id":902,"point":[-5,-0.5391048234334587,0.8402705570843298],"type":3,"volume":0.007114702339142866},{"fixed":false,"mass":0.015302148062196867,"nu":0,"particle_id":903,"point":[-4.628747665391915,-0.407575856505218,0.9105742546075779],"type":1,"volume":0.015302148062196867},{"fixed":false,"mass":0.017590454156708343,"nu":0,"particle_id":904,"point":[-0.3776344181208402,-0.069295128800567,-0.9931750255186167],"type":1,"volume":0.017590454156708343},{"fixed":false,"mass":0.03826396308753533,"nu":0,"particle_id":905,"point":[-1.957662369118821,0.4999752936494293,-0.477768005489685],"type":1,"volume":0.03826396308753533},{"fixed":false,"mass":0.01938390312650966,"nu":0,"particle_id":906,"point":[-2.329940771192556,0.5083998349155636,-0.8566827153763861],"type":1,"volume":0.01938390312650966},{"fixed":false,"mass":0.014400340208420098,"nu":0,"particle_id":907,"point":[-2.313483057881715,0.7683452645368496,-0.6324874733225441],"type":1,"volume":0.014400340208420098},{"fixed":false,"mass":0.017655656239148738,"nu":0,"particle_id":908,"point":[0.5879091870512756,0.448737393469377,0.8885729547273848],"type":1,"volume":0.017655656239148738},{"fixed":false,"mass":0.01793828437968264,"nu":0,"particle_id":909,"point":[0.3971667678031106,0.1870150801619561,0.9815806223058964],"type":1,"volume":0.01793828437968264},{"fixed":false,"mass":0.0170887787934123,"nu":0,"particle_id":910,"point":[5,0.449295900987054,-0.1377719299644467],"type":2,"volume":0.0170887787934123},{"fixed":false,"mass":0.018894093646532006,"nu":0,"particle_id":911,"point":[-4.527527950004503,0.7604588312474805,-0.6420971200899545],"type":1,"volume":0.018894093646532006},{"fixed":false,"mass":0.05176040981554773,"nu":0,"particle_id":912,"point":[2.839058548800647,-0.2533322565504474,-0.580638375505475],"type":1,"volume":0.05176040981554773},{"fixed":false,"mass":0.01979321789939595,"nu":0,"particle_id":913,"point":[0.3319953517398676,0.7990960811237033,0.5950174948967535],"type":1,"volume":0.01979321789939595},{"fixed":false,"mass":0.028922860379919667,"nu":0,"particle_id":914,"point":[-0.2031165366154546,-0.4588089938354433,-0.8831895721748764],"type":1,"volume":0.028922860379919667},{"fixed":false,"mass":0.007540242819340392,"nu":0,"particle_id":915,"point":[5,-0.3648174218556645,-0.9292991275486149],"type":2,"volume":0.007540242819340392},{"fixed":false,"mass":0.017371579095752935,"nu":0,"particle_id":916,"point":[5,-0.2928994367879654,-0.5157452132320554],"type":2,"volume":0.017371579095752935},{"fixed":false,"mass":0.013298723264750255,"nu":0,"particle_id":917,"point":[5,-0.6205144679482929,-0.778171256109975],"type":2,"volume":0.013298723264750255},{"fixed":false,"mass":0.014915044948456455,"nu":0,"particle_id":918,"point":[-5,-0.8754743362114682,-0.4732431850888849],"type":3,"volume":0.014915044948456455},{"fixed":false,"mass":0.027671370458642514,"nu":0,"particle_id":919,"point":[2.275974317405184,-0.6474624523098396,0.7560556168888711],"type":1,"volume":0.027671370458642514},{"fixed":false,"mass":0.010892520241565404,"nu":0,"particle_id":920,"point":[4.30157473621041,-0.7147242078120768,-0.6978249199874322],"type":1,"volume":0.010892520241565404},{"fixed":false,"mass":0.013523218802546253,"nu":0,"particle_id":921,"point":[-0.7995855620215795,-0.8206048260450199,0.5688090133791566],"type":1,"volume":0.013523218802546253},{"fixed":false,"mass":0.015513871180547728,"nu":0,"particle_id":922,"point":[-0.05464247259885766,0.8667620143490591,0.4895427928546083],"type":1,"volume":0.015513871180547728},{"fixed":false,"mass":0.015464217511409556,"nu":0,"particle_id":923,"point":[-1.326088918684652,0.8917268248518182,-0.4428369174786894],"type":1,"volume":0.015464217511409556},{"fixed":false,"mass":0.013439070984278592,"nu":0,"particle_id":924,"point":[-1.091917287969441,0.9518074985066813,-0.2906172668040216],"type":1,"volume":0.013439070984278592},{"fixed":false,"mass":0.02202344273674177,"nu":0,"particle_id":925,"point":[-1.56668683122494,-0.5455569851404194,-0.8368218048010045],"type":1,"volume":0.02202344273674177},{"fixed":false,"mass":0.017503390418905793,"nu":0,"particle_id":926,"point":[0.6270329530270939,0.06518996979417221,-0.9935793483901607],"type":1,"volume":0.017503390418905793},{"fixed":false,"mass":0.019146708066749094,"nu":0,"particle_id":927,"point":[2.468057117831111,-0.1746850259655029,0.982795026647175],"type":1,"volume":0.019146708066749094},{"fixed":false,"mass":0.026585669450483667,"nu":0,"particle_id":928,"point":[-2.584171198406722,0.7110837389103476,-0.7022608441789827],"type":1,"volume":0.026585669450483667},{"fixed":false,"mass":0.014780692143507105,"nu":0,"particle_id":929,"point":[-4.339723223550493,-0.7957762932357462,-0.5990626681424334],"type":1,"volume":0.014780692143507105},{"fixed":false,"mass":0.017890050561206468,"nu":0,"particle_id":930,"point":[5,-0.2303790259489255,0.4099653579356002],"type":2,"volume":0.017890050561206468},{"fixed":false,"mass":0.011740031035969992,"nu":0,"particle_id":931,"point":[5,0.4979412994680972,0.8622729190387929],"type":2,"volume":0.011740031035969992},{"fixed":false,"mass":0.017101155927670468,"nu":0,"particle_id":932,"point":[0.5067524745461469,-0.9531556491633695,-0.2861730096898309],"type":1,"volume":0.017101155927670468},{"fixed":false,"mass":0.01709011934971625,"nu":0,"particle_id":933,"point":[0.7723978277522143,-0.9841888401537169,0.1605333999450314],"type":1,"volume":0.01709011934971625},{"fixed":false,"mass":0.03842695162221376,"nu":0,"particle_id":934,"point":[3.510948687213142,0.04183444396393932,0.6610923674129817],"type":1,"volume":0.03842695162221376},{"fixed":false,"mass":0.01439673458221944,"nu":0,"particle_id":935,"point":[4.363494735650864,0.8254937487210299,0.5628518438621128],"type":1,"volume":0.01439673458221944},{"fixed":false,"mass":0.016670330687456585,"nu":0,"particle_id":936,"point":[-3.025257855722505,0.9814017653359453,0.1888310454528824],"type":1,"volume":0.016670330687456585},{"fixed":false,"mass":0.02002641727319202,"nu":0,"particle_id":937,"point":[-1.271902236156503,-0.5506122792360834,0.8341196938113655],"type":1,"volume":0.02002641727319202},{"fixed":false,"mass":0.015906407839648806,"nu":0,"particle_id":938,"point":[4.580847897476351,0.9509856974164279,-0.2933263819342119],"type":1,"volume":0.015906407839648806},{"fixed":false,"mass":0.0190412149588889,"nu":0,"particle_id":939,"point":[5,0.8974766981659327,-0.4320796611235209],"type":2,"volume":0.0190412149588889},{"fixed":false,"mass":0.020139544679042838,"nu":0,"particle_id":940,"point":[4.526966716208524,0.8271036679545477,-0.5608901516001582],"type":1,"volume":0.020139544679042838},{"fixed":false,"mass":0.006364857660482268,"nu":0,"particle_id":941,"point":[-5,0.6565945984642336,-0.7485610582252125],"type":3,"volume":0.006364857660482268},{"fixed":false,"mass":0.01692233171531006,"nu":0,"particle_id":942,"point":[-5,0.5882179477292848,-0.06010530840869419],"type":3,"volume":0.01692233171531006},{"fixed":false,"mass":0.018917082637016462,"nu":0,"particle_id":943,"point":[-5,0.4074084651670587,0.219319243420286],"type":3,"volume":0.018917082637016462},{"fixed":false,"mass":0.011016599252804094,"nu":0,"particle_id":944,"point":[5,0.1779918422150383,-0.2210388615188594],"type":2,"volume":0.011016599252804094},{"fixed":false,"mass":0.011015413922088794,"nu":0,"particle_id":945,"point":[4.227243727968061,0.825493748721031,-0.5628518438621098],"type":1,"volume":0.011015413922088794},{"fixed":false,"mass":0.014767331294081455,"nu":0,"particle_id":946,"point":[4.085610236382966,0.3646659590504697,0.9293450732882533],"type":1,"volume":0.014767331294081455},{"fixed":false,"mass":0.01335891465075578,"nu":0,"particle_id":947,"point":[-4.363025176117931,0.6998251703440379,0.7130826447680633],"type":1,"volume":0.01335891465075578},{"fixed":false,"mass":0.01161382951238689,"nu":0,"particle_id":948,"point":[-1.356877094646717,-0.2546145637265111,0.962728799086144],"type":1,"volume":0.01161382951238689},{"fixed":false,"mass":0.022832082116180066,"nu":0,"particle_id":949,"point":[-1.037072523066932,-0.161636974820295,0.9840801475155425],"type":1,"volume":0.022832082116180066},{"fixed":false,"mass":0.01643909808659953,"nu":0,"particle_id":950,"point":[1.109879798912506,0.5031144331794252,-0.8595078214623257],"type":1,"volume":0.01643909808659953},{"fixed":false,"mass":0.02988892559912434,"nu":0,"particle_id":951,"point":[-1.766940242041527,0.05657010767494611,0.3165516912135875],"type":1,"volume":0.02988892559912434},{"fixed":false,"mass":0.025142600118914837,"nu":0,"particle_id":952,"point":[3.03091997311019,0.4599800862076042,0.8825636102607295],"type":1,"volume":0.025142600118914837},{"fixed":false,"mass":0.014856731968742638,"nu":0,"particle_id":953,"point":[1.837827369481052,0.2267617827318211,0.9711778478301247],"type":1,"volume":0.014856731968742638},{"fixed":false,"mass":0.009296185771006554,"nu":0,"particle_id":954,"point":[-1.078950880825758,-0.2792100091359183,-0.955267852289355],"type":1,"volume":0.009296185771006554},{"fixed":false,"mass":0.022163174080120585,"nu":0,"particle_id":955,"point":[1.839155068427205,-0.5993555883812759,0.7955358998083237],"type":1,"volume":0.022163174080120585},{"fixed":false,"mass":0.015079115048246324,"nu":0,"particle_id":956,"point":[0.4916764545431682,0.9872598502099428,-0.1293529115821105],"type":1,"volume":0.015079115048246324},{"fixed":false,"mass":0.013801498231326554,"nu":0,"particle_id":957,"point":[-3.601686628168117,-0.1492013763129316,0.9853049470641191],"type":1,"volume":0.013801498231326554},{"fixed":false,"mass":0.0279062630642977,"nu":0,"particle_id":958,"point":[-0.2496633002004731,-0.1101098237825397,-0.3382155573050047],"type":1,"volume":0.0279062630642977},{"fixed":false,"mass":0.011120570088805567,"nu":0,"particle_id":959,"point":[4.125440368486037,0.0857827825630609,0.9915511333614816],"type":1,"volume":0.011120570088805567},{"fixed":false,"mass":0.004748023527992474,"nu":0,"particle_id":960,"point":[-5,-0.1765102913479226,-0.9826152536981612],"type":3,"volume":0.004748023527992474},{"fixed":false,"mass":0.00873378582331316,"nu":0,"particle_id":961,"point":[-5,0.1207701993433182,-0.9881051735829521],"type":3,"volume":0.00873378582331316},{"fixed":false,"mass":0.02399406272353588,"nu":0,"particle_id":962,"point":[1.536503746062925,-0.08411596179335432,0.9917153008782351],"type":1,"volume":0.02399406272353588},{"fixed":false,"mass":0.028505751372817946,"nu":0,"particle_id":963,"point":[1.735903681555198,0.9915392045582637,0.08590389773465265],"type":1,"volume":0.028505751372817946},{"fixed":false,"mass":0.012543724824608844,"nu":0,"particle_id":964,"point":[5,0.7307949394943577,-0.6782426767737948],"type":2,"volume":0.012543724824608844},{"fixed":false,"mass":0.017141616053507655,"nu":0,"particle_id":965,"point":[-3.840538358117914,0.8754876355926591,0.4732183036967188],"type":1,"volume":0.017141616053507655},{"fixed":false,"mass":0.015354217549660954,"nu":0,"particle_id":966,"point":[-5,-0.2441762422722216,-0.1745870161189224],"type":3,"volume":0.015354217549660954},{"fixed":false,"mass":0.009567470102835911,"nu":0,"particle_id":967,"point":[-5,-0.1455277744685972,-0.4457664316020963],"type":3,"volume":0.009567470102835911},{"fixed":false,"mass":0.009351458776675864,"nu":0,"particle_id":968,"point":[-5,-0.2168065382133226,-0.6489098659443657],"type":3,"volume":0.009351458776675864},{"fixed":false,"mass":0.011663762722754135,"nu":0,"particle_id":969,"point":[4.124937999039393,-0.4977671297229378,-0.8623660147071348],"type":1,"volume":0.011663762722754135},{"fixed":false,"mass":0.0064862038247827936,"nu":0,"particle_id":970,"point":[-4.646697831024541,0.6998251703440376,0.7130826447680636],"type":1,"volume":0.0064862038247827936},{"fixed":false,"mass":0.01157614839615208,"nu":0,"particle_id":971,"point":[-5,0.584434337432353,0.8077814539947368],"type":3,"volume":0.01157614839615208},{"fixed":false,"mass":0.014339171647622665,"nu":0,"particle_id":972,"point":[4.167131656990855,-0.4977671297229396,0.8623660147071255],"type":1,"volume":0.014339171647622665},{"fixed":false,"mass":0.03955799359845271,"nu":0,"particle_id":973,"point":[-3.383132852142184,-0.5964337559078083,-0.3136038018618766],"type":1,"volume":0.03955799359845271},{"fixed":false,"mass":0.016636441686453347,"nu":0,"particle_id":974,"point":[-3.502003745080589,0.1631585178551935,0.9839302886067669],"type":1,"volume":0.016636441686453347},{"fixed":false,"mass":0.025563172703745765,"nu":0,"particle_id":975,"point":[3.266669947298161,0.7636315508710978,0.6382311500428738],"type":1,"volume":0.025563172703745765},{"fixed":false,"mass":0.01078600848180496,"nu":0,"particle_id":976,"point":[-0.943619219313441,0.2656273929842567,-0.9593880938536729],"type":1,"volume":0.01078600848180496},{"fixed":false,"mass":0.014873436457016715,"nu":0,"particle_id":977,"point":[-1.529902565350081,0.9430791026421824,0.3193909318419983],"type":1,"volume":0.014873436457016715},{"fixed":false,"mass":0.00902457961238819,"nu":0,"particle_id":978,"point":[-1.982384169879702,0.6161730157820616,-0.7817341938241981],"type":1,"volume":0.00902457961238819},{"fixed":false,"mass":0.00925848404412511,"nu":0,"particle_id":979,"point":[3.677481968307688,0.9977315879499924,0.02303157405303171],"type":1,"volume":0.00925848404412511},{"fixed":false,"mass":0.012119597352368228,"nu":0,"particle_id":980,"point":[-2.212051260567566,0.9039280545498317,-0.4200100222516882],"type":1,"volume":0.012119597352368228},{"fixed":false,"mass":0.017861087698817706,"nu":0,"particle_id":981,"point":[-0.344841364631034,-0.06703191467103983,0.9933979326543318],"type":1,"volume":0.017861087698817706},{"fixed":false,"mass":0.01841320785948885,"nu":0,"particle_id":982,"point":[-3.38698597749798,0.4994438909225991,-0.8614697671735772],"type":1,"volume":0.01841320785948885},{"fixed":false,"mass":0.008397107962555609,"nu":0,"particle_id":983,"point":[-3.107479011044399,0.4858933071279471,-0.8687127051104528],"type":1,"volume":0.008397107962555609},{"fixed":false,"mass":0.016381252106837843,"nu":0,"particle_id":984,"point":[-0.4411892322856439,0.9834839450543891,0.1676903199938978],"type":1,"volume":0.016381252106837843},{"fixed":false,"mass":0.017696108316589992,"nu":0,"particle_id":985,"point":[-0.3736647980878536,0.8806709631755958,0.4635209798538455],"type":1,"volume":0.017696108316589992},{"fixed":false,"mass":0.009848429503069182,"nu":0,"particle_id":986,"point":[-5,0.8490715018661168,-0.5226394138473112],"type":3,"volume":0.009848429503069182},{"fixed":false,"mass":0.011682325829434778,"nu":0,"particle_id":987,"point":[-5,0.9645264952912471,-0.2486883535444012],"type":3,"volume":0.011682325829434778},{"fixed":false,"mass":0.01761535949737005,"nu":0,"particle_id":988,"point":[-1.201143646140392,-0.9836878489271653,0.1656200492309055],"type":1,"volume":0.01761535949737005},{"fixed":false,"mass":0.03138144205038209,"nu":0,"particle_id":989,"point":[-1.112139267602656,0.02023541635997546,0.3897646838745212],"type":1,"volume":0.03138144205038209},{"fixed":false,"mass":0.020954543507588106,"nu":0,"particle_id":990,"point":[-2.161383284366988,0.696611058009545,0.7157203985923224],"type":1,"volume":0.020954543507588106},{"fixed":false,"mass":0.016066141011998287,"nu":0,"particle_id":991,"point":[-2.292481192811842,0.9339800299948684,0.3493865544712289],"type":1,"volume":0.016066141011998287},{"fixed":false,"mass":0.021374237113973193,"nu":0,"particle_id":992,"point":[3.104657000610138,0.5601944060992201,-0.8276746515309821],"type":1,"volume":0.021374237113973193},{"fixed":false,"mass":0.017944942907841387,"nu":0,"particle_id":993,"point":[2.610442561368638,-0.006016093087303043,-0.9994074665491042],"type":1,"volume":0.017944942907841387},{"fixed":false,"mass":0.006603123699998064,"nu":0,"particle_id":994,"point":[5,0.2218893377802632,0.9726558878472392],"type":2,"volume":0.006603123699998064},{"fixed":false,"mass":0.008281972193445107,"nu":0,"particle_id":995,"point":[-5,0.06982731638799593,-0.259822573245374],"type":3,"volume":0.008281972193445107},{"fixed":false,"mass":0.022820701595591273,"nu":0,"particle_id":996,"point":[-2.368167634263179,0.4205863284215421,0.9036200124843283],"type":1,"volume":0.022820701595591273},{"fixed":false,"mass":0.014522575376168486,"nu":0,"particle_id":997,"point":[3.672323183772062,-0.2070190066272035,0.9771667534866637],"type":1,"volume":0.014522575376168486},{"fixed":false,"mass":0.02725849665387228,"nu":0,"particle_id":998,"point":[3.73266771130354,-0.5002540417851093,0.8610367325157655],"type":1,"volume":0.02725849665387228},{"fixed":false,"mass":0.01855724061291899,"nu":0,"particle_id":999,"point":[0.1613098429978297,-0.9948720221109452,-0.05206523325146501],"type":1,"volume":0.01855724061291899},{"fixed":false,"mass":0.05132624302976354,"nu":0,"particle_id":1000,"point":[0.2413194306166689,-0.6225435975184763,0.2017239799100479],"type":1,"volume":0.05132624302976354},{"fixed":false,"mass":0.018012146219832027,"nu":0,"particle_id":1001,"point":[1.372882095137661,0.2993615974934478,-0.9491549347916788],"type":1,"volume":0.018012146219832027},{"fixed":false,"mass":0.01482971192504359,"nu":0,"particle_id":1002,"point":[0.4339759092147741,-0.9993430575433229,0.006670048697497093],"type":1,"volume":0.01482971192504359},{"fixed":false,"mass":0.012919658524484083,"nu":0,"particle_id":1003,"point":[0.3569514390370192,-0.8705465415691376,0.4824624404250055],"type":1,"volume":0.012919658524484083},{"fixed":false,"mass":0.023632931056365616,"nu":0,"particle_id":1004,"point":[-2.493479014048914,0.9978688878246185,0.02163754503175582],"type":1,"volume":0.023632931056365616},{"fixed":false,"mass":0.018932898574820608,"nu":0,"particle_id":1005,"point":[2.189691001906279,0.9816693826705685,0.1861138810557748],"type":1,"volume":0.018932898574820608},{"fixed":false,"mass":0.0059562746539401105,"nu":0,"particle_id":1006,"point":[4.700502539162661,-0.2221001761570676,-0.9725919307248585],"type":1,"volume":0.0059562746539401105},{"fixed":false,"mass":0.00891649219076992,"nu":0,"particle_id":1007,"point":[5,-0.0743201226728102,-0.9926801068202783],"type":2,"volume":0.00891649219076992},{"fixed":false,"mass":0.017392144988072275,"nu":0,"particle_id":1008,"point":[-1.016597024252175,0.005510379442670473,-0.9994572749956608],"type":1,"volume":0.017392144988072275},{"fixed":false,"mass":0.018316003466602275,"nu":0,"particle_id":1009,"point":[0.6210448425873312,0.935611875618706,0.3440070803842459],"type":1,"volume":0.018316003466602275},{"fixed":false,"mass":0.01857439599372155,"nu":0,"particle_id":1010,"point":[0.6637445625703706,0.769040573326093,0.6316402371114785],"type":1,"volume":0.01857439599372155},{"fixed":false,"mass":0.004965992767567558,"nu":0,"particle_id":1011,"point":[5,0.4979412994680995,-0.8622729190387917],"type":2,"volume":0.004965992767567558},{"fixed":false,"mass":0.03247257858543052,"nu":0,"particle_id":1012,"point":[-1.02166282382571,0.09552591792739831,0.6931447527655266],"type":1,"volume":0.03247257858543052},{"fixed":false,"mass":0.019788961121925658,"nu":0,"particle_id":1013,"point":[-0.2335848473453115,-0.4952143085965474,0.8637305260272723],"type":1,"volume":0.019788961121925658},{"fixed":false,"mass":0.01231697559821552,"nu":0,"particle_id":1014,"point":[3.301892205796323,0.8628236125692176,-0.4969110243374485],"type":1,"volume":0.01231697559821552},{"fixed":false,"mass":0.028593405599732016,"nu":0,"particle_id":1015,"point":[1.810536990236975,0.8919924324646697,0.4423400005858739],"type":1,"volume":0.028593405599732016},{"fixed":false,"mass":0.008207144389310219,"nu":0,"particle_id":1016,"point":[0.9555688169141461,0.3251786111121515,0.9413234293297981],"type":1,"volume":0.008207144389310219},{"fixed":false,"mass":0.009225087270246018,"nu":0,"particle_id":1017,"point":[-3.723152817159582,-0.9622695618398647,0.2561284660405836],"type":1,"volume":0.009225087270246018},{"fixed":false,"mass":0.01660565267815375,"nu":0,"particle_id":1018,"point":[-3.980497948181937,-0.9051315325751712,0.4177584732297981],"type":1,"volume":0.01660565267815375},{"fixed":false,"mass":0.013740708500435708,"nu":0,"particle_id":1019,"point":[-1.290049340381032,0.6972474095936946,-0.7151981583437006],"type":1,"volume":0.013740708500435708},{"fixed":false,"mass":0.0075092713848055916,"nu":0,"particle_id":1020,"point":[4.112426786755465,-0.9227720027163318,0.3847554748735866],"type":1,"volume":0.0075092713848055916},{"fixed":false,"mass":0.01703554034389921,"nu":0,"particle_id":1021,"point":[-3.540820465114851,-0.999101886207592,0.009118702361780114],"type":1,"volume":0.01703554034389921},{"fixed":false,"mass":0.006964364711383569,"nu":0,"particle_id":1022,"point":[-5,0.9954250667626737,0.04645007667050866],"type":3,"volume":0.006964364711383569},{"fixed":false,"mass":0.014385596533002315,"nu":0,"particle_id":1023,"point":[-3.897565509429982,-0.2867448152637051,0.9529821938388665],"type":1,"volume":0.014385596533002315},{"fixed":false,"mass":0.01035807121332118,"nu":0,"particle_id":1024,"point":[1.215681715135308,0.4026863588416098,0.9131877455579819],"type":1,"volume":0.01035807121332118},{"fixed":false,"mass":0.009769861270907825,"nu":0,"particle_id":1025,"point":[0.7590240831048151,0.141265010020894,0.9860866109177782],"type":1,"volume":0.009769861270907825},{"fixed":false,"mass":0.013981167538005606,"nu":0,"particle_id":1026,"point":[3.559460892036901,0.9529435732543861,-0.2868721302685079],"type":1,"volume":0.013981167538005606},{"fixed":false,"mass":0.02349557872856551,"nu":0,"particle_id":1027,"point":[-3.283069293434385,0.6507451006875258,0.7533616169875559],"type":1,"volume":0.02349557872856551},{"fixed":false,"mass":0.016989957711702815,"nu":0,"particle_id":1028,"point":[-5,0.2734215739068337,0.5253203130299532],"type":3,"volume":0.016989957711702815},{"fixed":false,"mass":0.016638305647799723,"nu":0,"particle_id":1029,"point":[-3.276976891908061,-0.9639715459539244,-0.2505177763378972],"type":1,"volume":0.016638305647799723},{"fixed":false,"mass":0.00900476140405003,"nu":0,"particle_id":1030,"point":[0.1670776802986834,-0.9714554564104547,0.225846629887463],"type":1,"volume":0.00900476140405003},{"fixed":false,"mass":0.005915954675994636,"nu":0,"particle_id":1031,"point":[-0.7176233233654546,0.9434934460111863,-0.3180250248075879],"type":1,"volume":0.005915954675994636},{"fixed":false,"mass":0.013450063661136737,"nu":0,"particle_id":1032,"point":[0.9799598183595095,0.7417118864481768,-0.6649403384219092],"type":1,"volume":0.013450063661136737},{"fixed":false,"mass":0.010032970568193186,"nu":0,"particle_id":1033,"point":[1.387245277489384,0.9224073529924759,0.3854376865233187],"type":1,"volume":0.010032970568193186},{"fixed":false,"mass":0.005949045146047745,"nu":0,"particle_id":1034,"point":[-2.057242895266359,0.7960216541923506,-0.5987636949517685],"type":1,"volume":0.005949045146047745},{"fixed":false,"mass":0.011255192264081304,"nu":0,"particle_id":1035,"point":[-3.309153638293909,0.3930180628342507,0.9183555574395839],"type":1,"volume":0.011255192264081304},{"fixed":false,"mass":0.013895953148563421,"nu":0,"particle_id":1036,"point":[-1.348798025386405,0.4415104789011309,-0.8924358210426773],"type":1,"volume":0.013895953148563421},{"fixed":false,"mass":0.009243383564207676,"nu":0,"particle_id":1037,"point":[-4.625357468721793,0.9164034369759859,-0.396670223345604],"type":1,"volume":0.009243383564207676},{"fixed":false,"mass":0.019472056453767723,"nu":0,"particle_id":1038,"point":[-2.0127287757599,-0.4533784759674835,-0.8860922444492805],"type":1,"volume":0.019472056453767723},{"fixed":false,"mass":0.01053709132402127,"nu":0,"particle_id":1039,"point":[-5,-0.7604051373791183,0.6421625462578562],"type":3,"volume":0.01053709132402127},{"fixed":false,"mass":0.014012175570071533,"nu":0,"particle_id":1040,"point":[0.8194661920390395,-0.9881238204969696,-0.1205808740480965],"type":1,"volume":0.014012175570071533},{"fixed":false,"mass":0.014221355627230196,"nu":0,"particle_id":1041,"point":[-1.579920744404556,0.3329641709816509,-0.9389617055633595],"type":1,"volume":0.014221355627230196},{"fixed":false,"mass":0.010922667161967879,"nu":0,"particle_id":1042,"point":[-1.573150465218438,0.5564926431155143,-0.830712609900384],"type":1,"volume":0.010922667161967879},{"fixed":false,"mass":0.015846093645865294,"nu":0,"particle_id":1043,"point":[-4.639402369226559,-0.7899213520790904,-0.6061969345839286],"type":1,"volume":0.015846093645865294},{"fixed":false,"mass":0.01598580651581511,"nu":0,"particle_id":1044,"point":[-1.749489556373944,0.7021987255644131,-0.7111347183398407],"type":1,"volume":0.01598580651581511},{"fixed":false,"mass":0.004761896249862649,"nu":0,"particle_id":1045,"point":[-3.021734139942147,-0.9409091115683528,-0.3265444337297547],"type":1,"volume":0.004761896249862649},{"fixed":false,"mass":0.011548125721064733,"nu":0,"particle_id":1046,"point":[-1.55561753735395,0.8222968814728506,-0.5667472378748547],"type":1,"volume":0.011548125721064733},{"fixed":false,"mass":0.018380178069471342,"nu":0,"particle_id":1047,"point":[2.022423120467987,-0.1262354888433054,0.9875668895503452],"type":1,"volume":0.018380178069471342},{"fixed":false,"mass":0.01067799249785435,"nu":0,"particle_id":1048,"point":[-2.862954416515959,0.9899379122074038,-0.1021620918133078],"type":1,"volume":0.01067799249785435},{"fixed":false,"mass":0.008733230980521962,"nu":0,"particle_id":1049,"point":[1.246847026688676,0.8101232211797889,0.5815808858612608],"type":1,"volume":0.008733230980521962},{"fixed":false,"mass":0.018834907107490573,"nu":0,"particle_id":1050,"point":[1.991238425976736,0.4139884339489344,0.907146660553765],"type":1,"volume":0.018834907107490573},{"fixed":false,"mass":0.006108475999075238,"nu":0,"particle_id":1051,"point":[-1.078983625684152,0.4850161335979228,-0.8691815641304121],"type":1,"volume":0.006108475999075238},{"fixed":false,"mass":0.016409856849851724,"nu":0,"particle_id":1052,"point":[-0.08867280886313098,0.8455127545741612,-0.5292973617413717],"type":1,"volume":0.016409856849851724},{"fixed":false,"mass":0.0107893580170935,"nu":0,"particle_id":1053,"point":[-1.360185774692487,-0.7117886848740509,-0.7014018650368614],"type":1,"volume":0.0107893580170935},{"fixed":false,"mass":0.01145410519412495,"nu":0,"particle_id":1054,"point":[0.5198823332627864,-0.9599732301422427,0.2636984571488241],"type":1,"volume":0.01145410519412495},{"fixed":false,"mass":0.011886562217206489,"nu":0,"particle_id":1055,"point":[2.222944519093411,0.3254521988863885,0.9412404373858082],"type":1,"volume":0.011886562217206489},{"fixed":false,"mass":0.013683452863685582,"nu":0,"particle_id":1056,"point":[0.5680000480319429,-0.017274607018516,0.9982985997123028],"type":1,"volume":0.013683452863685582},{"fixed":false,"mass":0.016742165371781137,"nu":0,"particle_id":1057,"point":[2.373995485045244,0.09175352030398484,0.9909630670223006],"type":1,"volume":0.016742165371781137},{"fixed":false,"mass":0.021206067595278093,"nu":0,"particle_id":1058,"point":[-2.998080836239336,0.9274268869274227,-0.3709893720445633],"type":1,"volume":0.021206067595278093},{"fixed":false,"mass":0.019691557222636685,"nu":0,"particle_id":1059,"point":[3.285570800672676,0.7069732768365413,-0.7072163453750809],"type":1,"volume":0.019691557222636685}],"rho_0":1,"size":null,"types":[{"fixed":false,"mass":1,"name":"Un-Assigned","nu":0,"typeID":0,"volume":1},{"fixed":false,"mass":1,"name":"Middle","nu":0,"typeID":1,"volume":1},{"fixed":false,"mass":1,"name":"Edge 1","nu":0,"typeID":2,"volume":1},{"fixed":false,"mass":1,"name":"Edge 2","nu":0,"typeID":3,"volume":1}],"x_lim":[-5,5],"y_lim":[-1,0.9999999999999999],"z_lim":[-0.9997191433003008,0.9999488265847117]},"eventsCollection":[],"functionDefinitions":[],"initialConditions":[],"is_spatial":true,"modelSettings":{"endSim":500,"timeStep":1},"parameters":[{"compID":3,"expression":1,"name":"k_react"},{"compID":4,"expression":196.38595510240296,"name":"k_creat1"},{"compID":5,"expression":197.70475491603773,"name":"k_creat2"}],"reactions":[{"annotation":"","compID":6,"massaction":true,"name":"r1","products":[{"ratio":1,"specie":{"annotation":"","compID":1,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"A","switchMin":100,"switchTol":0.03,"types":[1,2],"value":0}}],"propensity":"","rate":{"compID":4,"expression":196.38595510240296,"name":"k_creat1"},"reactants":[],"reactionType":"creation","summary":"\\emptyset \\rightarrow A","types":[2]},{"annotation":"","compID":7,"massaction":true,"name":"r2","products":[{"ratio":1,"specie":{"annotation":"","compID":2,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"B","switchMin":100,"switchTol":0.03,"types":[1,3],"value":0}}],"propensity":"","rate":{"compID":5,"expression":197.70475491603773,"name":"k_creat2"},"reactants":[],"reactionType":"creation","summary":"\\emptyset \\rightarrow B","types":[3]},{"annotation":"","compID":8,"massaction":true,"name":"r3","products":[],"propensity":"","rate":{"compID":3,"expression":1,"name":"k_react"},"reactants":[{"ratio":1,"specie":{"annotation":"","compID":1,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"A","switchMin":100,"switchTol":0.03,"types":[1,2],"value":0}},{"ratio":1,"specie":{"annotation":"","compID":2,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"B","switchMin":100,"switchTol":0.03,"types":[1,3],"value":0}}],"reactionType":"custom-massaction","summary":"A + B \\rightarrow \\emptyset","types":[1,2,3]}],"rules":[],"species":[{"annotation":"","compID":1,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"A","switchMin":100,"switchTol":0.03,"types":[1,2],"value":0,"diffusionConst":0.1},{"annotation":"","compID":2,"diffusionCoeff":0.1,"isSwitchTol":true,"mode":"discrete","name":"B","switchMin":100,"switchTol":0.03,"types":[1,3],"value":0,"diffusionConst":0.1}],"volume":1,"name":"cylinder_demo3d"} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index eb3d418969..a5b7759e21 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ python-libsbml==5.18.0 python-libsedml==2.0.9 python-libcombine==0.2.7 -gillespy2==1.5.11 +escapism==1.0.1 +gillespy2==1.6.3 sciope==0.4 pygmsh==5.0.2 meshio==2.3.10 diff --git a/stochss/handlers/__init__.py b/stochss/handlers/__init__.py index ce3865a3a9..de707d4ddb 100644 --- a/stochss/handlers/__init__.py +++ b/stochss/handlers/__init__.py @@ -66,6 +66,7 @@ def get_page_handlers(route_start): (r"/stochss/api/file/json-data\/?", JsonFileAPIHandler), (r"/stochss/api/file/duplicate\/?", DuplicateModelHandler), (r"/stochss/api/file/unzip\/?", UnzipFileAPIHandler), + (r"/stochss/api/notebook/presentation\/?", NotebookPresentationAPIHandler), (r"/stochss/api/directory/duplicate\/?", DuplicateDirectoryHandler), (r"/stochss/api/directory/create\/?", CreateDirectoryHandler), (r"/stochss/api/spatial/to-model\/?", ConvertToModelAPIHandler), @@ -75,6 +76,7 @@ def get_page_handlers(route_start): (r"/stochss/api/model/to-sbml\/?", ModelToSBMLAPIHandler), (r"/stochss/api/model/run\/?", RunModelAPIHandler), (r"/stochss/api/model/exists\/?", ModelExistsAPIHandler), + (r"/stochss/api/model/presentation\/?", ModelPresentationAPIHandler), (r"/stochss/api/model/new-bc\/?", CreateNewBoundCondAPIHandler), (r"/stochss/api/spatial-model/domain-list\/?", LoadExternalDomains), (r"/stochss/api/spatial-model/types-list\/?", LoadParticleTypesDescriptions), @@ -105,7 +107,8 @@ def get_page_handlers(route_start): (r"/stochss/api/workflow/edit-model\/?", GetWorkflowModelPathAPIHandler), (r"/stochss/api/workflow/save-plot\/?", SavePlotAPIHandler), (r"/stochss/api/workflow/save-annotation\/?", SaveAnnotationAPIHandler), - (r"/stochss/api/workflow/update-format\/?", UpadteWorkflowAPIHandler) + (r"/stochss/api/workflow/update-format\/?", UpadteWorkflowAPIHandler), + (r"/stochss/api/job/presentation\/?", JobPresentationAPIHandler) ] full_handlers = list(map(lambda h: (url_path_join(route_start, h[0]), h[1]), handlers)) return full_handlers diff --git a/stochss/handlers/file_browser.py b/stochss/handlers/file_browser.py index 2afb26ca41..b488081f81 100644 --- a/stochss/handlers/file_browser.py +++ b/stochss/handlers/file_browser.py @@ -730,3 +730,37 @@ async def get(self): except StochSSAPIError as err: report_error(self, log, err) self.finish() + + +class NotebookPresentationAPIHandler(APIHandler): + ''' + ################################################################################################ + Handler publishing notebook presentations. + ################################################################################################ + ''' + @web.authenticated + async def get(self): + ''' + Publish a notebook presentation. + + Attributes + ---------- + ''' + self.set_header('Content-Type', 'application/json') + path = self.get_query_argument(name="path") + log.debug("Path to the file: %s", path) + try: + notebook = StochSSNotebook(path=path) + log.info("Publishing the %s presentation", notebook.get_name()) + links, exists = notebook.publish_presentation() + if exists: + message = f"A presentation for {notebook.get_name()} already exists." + else: + message = f"Successfully published the {notebook.get_name()} presentation" + resp = {"message": message, "links": links} + log.info(resp['message']) + log.debug("Response Message: %s", resp) + self.write(resp) + except StochSSAPIError as err: + report_error(self, log, err) + self.finish() diff --git a/stochss/handlers/models.py b/stochss/handlers/models.py index 04c210ad94..1900659ece 100644 --- a/stochss/handlers/models.py +++ b/stochss/handlers/models.py @@ -408,6 +408,43 @@ async def get(self): self.finish() +class ModelPresentationAPIHandler(APIHandler): + ''' + ################################################################################################ + Handler publishing model presentations. + ################################################################################################ + ''' + @web.authenticated + async def get(self): + ''' + Publish a model or spatial model presentation. + + Attributes + ---------- + ''' + self.set_header('Content-Type', 'application/json') + path = self.get_query_argument(name="path") + log.debug("Path to the file: %s", path) + file_objs = {"mdl":StochSSModel, "smdl":StochSSSpatialModel} + ext = path.split(".").pop() + try: + model = file_objs[ext](path=path) + log.info("Publishing the %s presentation", model.get_name()) + links, data = model.publish_presentation() + if data is None: + message = f"A presentation for {model.get_name()} already exists." + else: + message = f"Successfully published the {model.get_name()} presentation." + file_objs[ext](**data) + resp = {"message": message, "links": links} + log.info(resp['message']) + log.debug("Response Message: %s", resp) + self.write(resp) + except StochSSAPIError as err: + report_error(self, log, err) + self.finish() + + class CreateNewBoundCondAPIHandler(APIHandler): ''' ################################################################################################ diff --git a/stochss/handlers/util/stochss_folder.py b/stochss/handlers/util/stochss_folder.py index 70a7a20bb9..4bcfe716e9 100644 --- a/stochss/handlers/util/stochss_folder.py +++ b/stochss/handlers/util/stochss_folder.py @@ -19,9 +19,10 @@ import os import json import shutil -from urllib import request import traceback +import requests + from .stochss_base import StochSSBase from .stochss_file import StochSSFile from .stochss_model import StochSSModel @@ -375,6 +376,31 @@ def move(self, location): raise StochSSPermissionsError(message, traceback.format_exc()) from err + def publish_presentation(self, name=None): + ''' + Publish a job, workflow, or project presentation. + + Attributes + ---------- + ''' + present_dir = os.path.join(self.user_dir, ".presentations") + if not os.path.exists(present_dir): + os.mkdir(present_dir) + file = self.get_file() if name is None else name + dst = os.path.join(present_dir, file) + if os.path.exists(dst): + message = "A presentation with this name already exists" + raise StochSSFileExistsError(message) + src = self.get_path(full=True) + try: + shutil.copytree(src, dst) + # INSERT JUPYTER HUB CODE HERE + return {"message": f"Successfully published the {self.get_name()} presentation"} + except PermissionError as err: + message = f"You do not have permission to publish this directory: {str(err)}" + raise StochSSPermissionsError(message, traceback.format_exc()) from err + + def upload(self, file_type, file, body, new_name=None): ''' Upload a file from a remote location to the users file system @@ -417,17 +443,20 @@ def upload_from_link(self, remote_path): remote_path : str Path to the remote file ''' - response = request.urlopen(remote_path) - file = self.get_file(path=remote_path) + ext = remote_path.split('.').pop() + body = requests.get(remote_path, allow_redirects=True).content + if "presentation-download" in remote_path: + file = f"{json.loads(body)['name']}.{ext}" + else: + file = self.get_file(path=remote_path) path = self.get_new_path(dst_path=file) if os.path.exists(path): message = f"Could not upload this file as {file} already exists" return {"message":message, "reason":"File Already Exists"} try: file_types = {"mdl":"model", "smdl":"model", "sbml":"sbml"} - ext = file.split('.').pop() file_type = file_types[ext] if ext in file_types.keys() else "file" - _ = self.upload(file_type=file_type, file=file, body=response.read()) + _ = self.upload(file_type=file_type, file=file, body=body) new_path = self.__get_rmt_upld_path(file=file) message = f"Successfully uploaded the file {file} to {new_path}" return {"message":message, "file_path":new_path} diff --git a/stochss/handlers/util/stochss_model.py b/stochss/handlers/util/stochss_model.py index 3d0dbaecbe..29e4d4b1ab 100644 --- a/stochss/handlers/util/stochss_model.py +++ b/stochss/handlers/util/stochss_model.py @@ -19,17 +19,20 @@ import os import ast import json +import string +import hashlib import tempfile import traceback import numpy +from escapism import escape from gillespy2.sbml.SBMLexport import export from gillespy2 import Model, Species, Parameter, Reaction, Event, EventTrigger, EventAssignment, \ RateRule, AssignmentRule, FunctionDefinition from .stochss_base import StochSSBase from .stochss_errors import StochSSAPIError, StochSSFileNotFoundError, FileNotJSONFormatError, \ - StochSSModelFormatError + StochSSModelFormatError, StochSSPermissionsError class StochSSModel(StochSSBase): ''' @@ -461,6 +464,40 @@ def load(self): return self.model + def publish_presentation(self): + ''' + Publish a model or spatial model presentation + + Attributes + ---------- + ''' + present_dir = os.path.join(self.user_dir, ".presentations") + if not os.path.exists(present_dir): + os.mkdir(present_dir) + try: + self.load() + safe_chars = set(string.ascii_letters + string.digits) + hostname = escape(os.environ.get('JUPYTERHUB_USER'), safe=safe_chars) + model = json.dumps(self.model, sort_keys=True) + # replace with gillespy2.Model.to_json + file = f"{hashlib.md5(model.encode('utf-8')).hexdigest()}.mdl" + dst = os.path.join(present_dir, file) + if os.path.exists(dst): + data = None + else: + data = {"path": dst, "new":True, "model":self.model} + query_str = f"?owner={hostname}&file={file}" + present_link = f"https://live.stochss.org/stochss/present-model{query_str}" + downloadlink = os.path.join("https://live.stochss.org/stochss/download_presentation", + hostname, file) + open_link = f"https://live.stochss.org?open={downloadlink}" + links = {"presentation": present_link, "download": downloadlink, "open": open_link} + return links, data + except PermissionError as err: + message = f"You do not have permission to publish this file: {str(err)}" + raise StochSSPermissionsError(message, traceback.format_exc()) from err + + def save(self, model): ''' Saves the model to an existing file diff --git a/stochss/handlers/util/stochss_notebook.py b/stochss/handlers/util/stochss_notebook.py index ee84eaf346..2d2cbf8bd0 100644 --- a/stochss/handlers/util/stochss_notebook.py +++ b/stochss/handlers/util/stochss_notebook.py @@ -16,16 +16,20 @@ along with this program. If not, see . ''' +import os import json import string +import hashlib import traceback import nbformat +from escapism import escape from nbformat import v4 as nbf from gillespy2.solvers.utilities.cpp_support_test import check_cpp_support from .stochss_base import StochSSBase -from .stochss_errors import StochSSFileNotFoundError, StochSSModelFormatError +from .stochss_errors import StochSSFileNotFoundError, StochSSModelFormatError, \ + StochSSPermissionsError class StochSSNotebook(StochSSBase): ''' @@ -601,7 +605,7 @@ def __create_reaction_strings(self, model, pad): if reac['reactionType'] == 'custom-propensity': reac_str += f'propensity_function="{reac["propensity"]}")' else: - reac_str += f'rate=self.listOfParameters["{reac["rate"]["name"]}"])' + reac_str += f'rate="{reac["rate"]["name"]}")' if not self.s_model['is_spatial']: reac_str += ")" reactions.append(reac_str) @@ -866,6 +870,15 @@ def __get_gillespy2_solver_name(self): 'ODE': self.model.get_best_solver_algo("ODE").name} return algorithm_map[self.settings['simulationSettings']['algorithm']] + @classmethod + def __get_presentation_links(cls, hostname, file): + query_str = f"?owner={hostname}&file={file}" + present_link = f"https://live.stochss.org/stochss/present-notebook{query_str}" + dl_link_base = "https://live.stochss.org/stochss/notebook/download_presentation" + download_link = os.path.join(dl_link_base, hostname, file) + open_link = f"https://live.stochss.org?open={download_link}" + return {"presentation": present_link, "download": download_link, "open": open_link} + def create_1dps_notebook(self): '''Create a 1D parameter sweep jupiter notebook for a StochSS model/workflow @@ -938,7 +951,7 @@ def create_ses_notebook(self): species = self.s_model['species'][0]['name'] plot_str = f"results.plot_species('{species}', animated=True, width=None, height=None)" else: - plot_str = f"results.plot_property('type', animated=True, width=None, height=None)" + plot_str = "results.plot_property('type', animated=True, width=None, height=None)" cells = self.__create_common_cells() if 'boundaryConditions' in self.s_model.keys(): bc_cells = self.__create_boundary_condition_cells() @@ -1021,6 +1034,30 @@ def load(self): message = f"Could not find the notebook file: {str(err)}" raise StochSSFileNotFoundError(message, traceback.format_exc()) from err + def publish_presentation(self): + '''Publish a notebook presentation''' + present_dir = os.path.join(self.user_dir, ".presentations") + if not os.path.exists(present_dir): + os.mkdir(present_dir) + try: + notebook_pres = {"notebook": self.load(), "file": self.get_file()} + safe_chars = set(string.ascii_letters + string.digits) + hostname = escape(os.environ.get('JUPYTERHUB_USER'), safe=safe_chars) + nb_str = json.dumps(notebook_pres['notebook'], sort_keys=True) + file = f"{hashlib.md5(nb_str.encode('utf-8')).hexdigest()}.ipynb" + dst = os.path.join(present_dir, file) + if os.path.exists(dst): + exists = True + else: + exists = False + with open(dst, "w") as presentation_file: + json.dump(notebook_pres, presentation_file) + links = self.__get_presentation_links(hostname, file) + return links, exists + except PermissionError as err: + message = f"You do not have permission to publish this file: {str(err)}" + raise StochSSPermissionsError(message, traceback.format_exc()) from err + def write_notebook_file(self, cells): '''Write the new notebook file to disk diff --git a/stochss/handlers/util/stochss_sbml.py b/stochss/handlers/util/stochss_sbml.py index 4d4f334880..f68d67c535 100644 --- a/stochss/handlers/util/stochss_sbml.py +++ b/stochss/handlers/util/stochss_sbml.py @@ -21,8 +21,7 @@ import traceback from gillespy2.sbml.SBMLimport import convert -from gillespy2.sbml.SBMLimport import __read_sbml_model as _read_sbml_model -from gillespy2.sbml.SBMLimport import __get_math as _get_math +from gillespy2.stochss.StochSSexport import export from .stochss_base import StochSSBase from .stochss_errors import StochSSFileNotFoundError @@ -57,205 +56,6 @@ def __init__(self, path, new=False, document=None): sbml_file.write(document) - @classmethod - def __build_element(cls, stoich_species): - if not stoich_species: - return "\\emptyset" - - elements = [] - for species in stoich_species: - name = species['specie']['name'] - ratio = species['ratio'] - element = f"{ratio}{name}" if ratio > 1 else name - elements.append(element) - return '+'.join(elements) - - - @classmethod - def __convert_assignments(cls, model, event, assignments): - for assignment in assignments: - name = assignment.variable.name - try: - variable = cls.__get_species(species=model['species'], name=name) - except IndexError: - variable = cls.__get_parameter(parameters=model['parameters'], name=name) - - s_assignment = {"variable": variable, - "expression": assignment.expression} - event['eventAssignments'].append(s_assignment) - - - @classmethod - def __convert_events(cls, model, events): - for name, event in events.items(): - s_event = {"compID":model['defaultID'], - "name": name, - "annotation": "", - "delay": event.delay, - "priority": event.priority, - "triggerExpression": event.trigger.expression, - "initialValue": event.trigger.value, - "persistent": event.trigger.persistent, - "useValuesFromTriggerTime": event.use_values_from_trigger_time, - "eventAssignments": []} - - cls.__convert_assignments(model=model, event=s_event, assignments=event.assignments) - - model['eventsCollection'].append(s_event) - model['defaultID'] += 1 - - - @classmethod - def __convert_function_definition(cls, model, function_definitions): - for function_definition in function_definitions: - name = function_definition["name"] - variables = ', '.join(function_definition["args"]) - expression = function_definition["function"] - function = "lambda({0}, {1})".format(variables, expression) - signature = "{0}({1})".format(name, variables) - - s_function_definition = {"compID":model['defaultID'], - "name":name, - "function":function, - "expression":expression, - "variables":variables, - "signature":signature, - "annotation": ""} - model['functionDefinitions'].append(s_function_definition) - model['defaultID'] += 1 - - - @classmethod - def __convert_parameters(cls, model, parameters): - for name, parameter in parameters.items(): - s_parameter = {"compID":model['defaultID'], - "name":name, - "expression":str(parameter.expression), - "annotation": ""} - model['parameters'].append(s_parameter) - model['defaultID'] += 1 - - - @classmethod - def __convert_stoich_species(cls, s_reaction, reaction, key, species): - source = reaction.reactants if key == "reactants" else reaction.products - for specie, ratio in source.items(): - stoich_species = {"ratio":ratio, - "specie":cls.__get_species(species=species, name=specie.name)} - s_reaction[key].append(stoich_species) - - - @classmethod - def __convert_reactions(cls, model, reactions): - for name, reaction in reactions.items(): - s_reaction = {"compID":model['defaultID'], - "name":name, - "reactionType": "custom-propensity", - "massaction": False, - "propensity": reaction.propensity_function, - "annotation": "", - "rate": {}, - "subdomains": [ - "subdomain 1: ", - "subdomain 2: " - ], - "reactants": [], - "products": []} - - for key in ['reactants', 'products']: - cls.__convert_stoich_species(s_reaction=s_reaction, reaction=reaction, - key=key, species=model['species']) - cls.__get_summary(reaction=s_reaction) - - model['reactions'].append(s_reaction) - model['defaultID'] += 1 - - - @classmethod - def __convert_rules(cls, model, r_type, rules): - for name, rule in rules.items(): - try: - variable = cls.__get_species(species=model['species'], name=rule.variable) - except IndexError: - variable = cls.__get_parameter(parameters=model['parameters'], name=rule.variable) - - s_rule = {"compID":model['defaultID'], - "name":name, - "expression":rule.formula, - "type":r_type, - "variable":variable, - "annotation": ""} - model['rules'].append(s_rule) - model['defaultID'] += 1 - - - @classmethod - def __convert_species(cls, model, species): - mode = "dynamic" - - # Get the model for all species - for _, specie in species.items(): - if specie.mode != mode: - mode = "continuous" - break - - for name, specie in species.items(): - s_species = {"compID":model['defaultID'], - "name":name, - "value":specie.initial_value, - "mode":mode, - "switchTol": 0.03, - "switchMin": 100, - "isSwitchTol": True, - "annotation": "", - "diffusionConst":0, - "subdomains": [ - "subdomain 1: ", - "subdomain 2: " - ]} - model['species'].append(s_species) - model['defaultID'] += 1 - - model['defaultMode'] = mode - - - def __get_function_definitions(self): - path = self.get_path(full=True) - sb_model = _read_sbml_model(path)[0] - function_definitions = [] - - for i in range(sb_model.getNumFunctionDefinitions()): - function = sb_model.getFunctionDefinition(i) - function_name = function.getId() - function_tree = function.getMath() - num_nodes = function_tree.getNumChildren() - function_args = [function_tree.getChild(i).getName() for i in range(num_nodes-1)] - function_string = _get_math(function_tree.getChild(num_nodes-1)) - s_function_definition = {"name":function_name, - "function":function_string, - "args":function_args} - function_definitions.append(s_function_definition) - - return function_definitions - - - @classmethod - def __get_parameter(cls, parameters, name): - return list(filter(lambda parameter: parameter['name'] == name, parameters))[0] - - - @classmethod - def __get_summary(cls, reaction): - r_summary = cls.__build_element(reaction['reactants']) - p_summary = cls.__build_element(reaction['products']) - reaction['summary'] = f"{r_summary} \\rightarrow {p_summary}" - - - @classmethod - def __get_species(cls, species, name): - return list(filter(lambda specie: specie['name'] == name, species))[0] - - def convert_to_gillespy(self): ''' Convert the sbml model to a gillespy model and return it @@ -282,14 +82,14 @@ def convert_to_model(self, name=None, wkgp=False): Attributes ---------- ''' - s_model = self.get_model_template() # StochSS Model in json format - self.log("debug", f"Model template: \n{json.dumps(s_model)}") - g_model, errors = self.convert_to_gillespy() # GillesPy2 Model object if g_model is None: message = "ERROR! We were unable to convert the SBML Model into a StochSS Model." return {"message":message, "errors":errors, "model":None} + s_model = export(model=g_model, return_stochss_model=True) # StochSS Model in json format + self.log("debug", f"Model: \n{json.dumps(s_model)}") + s_file = f"{g_model.name}.mdl" if name is None else f"{name}.mdl" if wkgp: wkgp_path, changed = self.get_unique_path(name=f"{self.get_name(path=s_file)}.wkgp", @@ -300,15 +100,5 @@ def convert_to_model(self, name=None, wkgp=False): else: s_path = os.path.join(self.get_dir_name(), s_file) - self.__convert_species(model=s_model, species=g_model.get_all_species()) - self.__convert_parameters(model=s_model, parameters=g_model.get_all_parameters()) - self.__convert_reactions(model=s_model, reactions=g_model.get_all_reactions()) - self.__convert_events(model=s_model, events=g_model.get_all_events()) - self.__convert_rules(model=s_model, r_type='Rate Rule', rules=g_model.get_all_rate_rules()) - self.__convert_rules(model=s_model, r_type='Assignment Rule', - rules=g_model.get_all_assignment_rules()) - self.__convert_function_definition(model=s_model, - function_definitions=self.__get_function_definitions()) - message = "The SBML Model was successfully converted to a StochSS Model." return {"message":message, "errors":errors, "model":s_model, "path":s_path} diff --git a/stochss/handlers/workflows.py b/stochss/handlers/workflows.py index ae8bbc4c63..a7ec157b8b 100644 --- a/stochss/handlers/workflows.py +++ b/stochss/handlers/workflows.py @@ -28,7 +28,7 @@ # Use finish() for json, write() for text from .util import StochSSJob, StochSSModel, StochSSSpatialModel, StochSSNotebook, StochSSWorkflow, \ - StochSSAPIError, report_error + StochSSFolder, StochSSAPIError, report_error log = logging.getLogger('stochss') @@ -394,3 +394,34 @@ async def get(self): except StochSSAPIError as err: report_error(self, log, err) self.finish() + + +class JobPresentationAPIHandler(APIHandler): + ''' + ################################################################################################ + Handler for publishing job presentations. + ################################################################################################ + ''' + @web.authenticated + async def get(self): + ''' + Publish a job presentation. + + Attributes + ---------- + ''' + self.set_header('Content-Type', 'application/json') + path = self.get_query_argument(name="path") + log.debug("The path to the job: %s", path) + name = self.get_query_argument(name="name") + log.debug("Name of the job presentation: %s", name) + try: + folder = StochSSFolder(path=path) + log.info("Publishing the %s presentation", folder.get_name()) + resp = folder.publish_presentation(name=name) + log.info(resp['message']) + log.debug("Response Message: %s", resp) + self.write(resp) + except StochSSAPIError as err: + report_error(self, log, err) + self.finish() diff --git a/stochss/tests/example_models.py b/stochss/tests/example_models.py new file mode 100644 index 0000000000..17c415ac7c --- /dev/null +++ b/stochss/tests/example_models.py @@ -0,0 +1,352 @@ +''' +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + +import numpy as np + +from gillespy2.core import ( + Model, + Species, + Reaction, + Parameter +) + +# pylint: disable=line-too-long +# pylint: disable=missing-class-docstring +# pylint: disable=too-few-public-methods +class Brusselator(Model): + def __init__(self): + Model.__init__(self, name="Brusselator") + self.volume = 1000 + + # Parameters + self.add_parameter(Parameter(name="rate1", expression="5000")) + self.add_parameter(Parameter(name="rate2", expression="50")) + self.add_parameter(Parameter(name="rate3", expression="5e-05")) + self.add_parameter(Parameter(name="rate4", expression="5")) + + # Variables + self.add_species(Species(name="A", initial_value=100000, mode="discrete")) + self.add_species(Species(name="B", initial_value=100000, mode="discrete")) + self.add_species(Species(name="C", initial_value=0, mode="discrete")) + self.add_species(Species(name="D", initial_value=0, mode="discrete")) + self.add_species(Species(name="X", initial_value=2000, mode="discrete")) + self.add_species(Species(name="Y", initial_value=1000, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="reaction1", reactants={'A': 1}, products={'X': 1, 'A': 1}, propensity_function="rate1")) + self.add_reaction(Reaction(name="reaction2", reactants={'B': 1, 'X': 1}, products={'Y': 1, 'C': 1, 'B': 1}, propensity_function="rate2*X")) + self.add_reaction(Reaction(name="reaction3", reactants={'X': 2, 'Y': 1}, products={'X': 3}, propensity_function="rate3*Y*X*(X-1)/2")) + self.add_reaction(Reaction(name="reaction4", reactants={'X': 1}, products={'D': 1}, propensity_function="rate4*X")) + + # Timespan + self.timespan(np.arange(0, 30, 0.01)) + + +class Degradation(Model): + def __init__(self): + Model.__init__(self, name="Degradation") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="decayrate", expression="0.05")) + + # Variables + self.add_species(Species(name="protein", initial_value=50, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="reaction", reactants={'protein': 1}, products={}, rate=self.listOfParameters["decayrate"])) + + # Timespan + self.timespan(np.arange(0, 100, 1)) + + +class Dimerization(Model): + def __init__(self): + Model.__init__(self, name="Dimerization") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="k_c", expression="0.005")) + self.add_parameter(Parameter(name="k_d", expression="0.08")) + + # Variables + self.add_species(Species(name="Monomer", initial_value=30, mode="discrete")) + self.add_species(Species(name="Dimer", initial_value=0, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="r_creation", reactants={'Monomer': 2}, products={'Dimer': 1}, rate=self.listOfParameters["k_c"])) + self.add_reaction(Reaction(name="r_dissociation", reactants={'Dimer': 1}, products={'Monomer': 2}, rate=self.listOfParameters["k_d"])) + + # Timespan + self.timespan(np.arange(0, 100, 1)) + + +class LotkavolterraOscillator(Model): + def __init__(self): + Model.__init__(self, name="Lotkavolterra_Oscillator") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="k1", expression="0.004")) + self.add_parameter(Parameter(name="k2", expression="0.5")) + self.add_parameter(Parameter(name="k3", expression="0.0045")) + + # Variables + self.add_species(Species(name="R", initial_value=0.0095, mode="continuous")) + self.add_species(Species(name="W", initial_value=0.008, mode="continuous")) + + # Reactions + self.add_reaction(Reaction(name="r1", reactants={'R': 1}, products={'R': 2}, rate=self.listOfParameters["k1"])) + self.add_reaction(Reaction(name="r2", reactants={'R': 1, 'W': 1}, products={'W': 2}, rate=self.listOfParameters["k2"])) + self.add_reaction(Reaction(name="r3", reactants={'W': 1}, products={}, rate=self.listOfParameters["k3"])) + + # Timespan + self.timespan(np.arange(0, 9000, 1)) + + +class MichaelisMenten(Model): + def __init__(self): + Model.__init__(self, name="Michaelis_Menten") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="rate1", expression="0.0017")) + self.add_parameter(Parameter(name="rate2", expression="0.5")) + self.add_parameter(Parameter(name="rate3", expression="0.1")) + + # Variables + self.add_species(Species(name="A", initial_value=301, mode="discrete")) + self.add_species(Species(name="B", initial_value=120, mode="discrete")) + self.add_species(Species(name="C", initial_value=0, mode="discrete")) + self.add_species(Species(name="D", initial_value=0, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="r1", reactants={'A': 1, 'B': 1}, products={'C': 1}, rate=self.listOfParameters["rate1"])) + self.add_reaction(Reaction(name="r2", reactants={'C': 1}, products={'A': 1, 'B': 1}, rate=self.listOfParameters["rate2"])) + self.add_reaction(Reaction(name="r3", reactants={'C': 1}, products={'B': 1, 'D': 1}, rate=self.listOfParameters["rate3"])) + + # Timespan + self.timespan(np.arange(0, 100, 1)) + + +class Opioid(Model): + def __init__(self): + Model.__init__(self, name="Opioid") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="alpha", expression="0.15")) + self.add_parameter(Parameter(name="epsilon", expression="0.8")) + self.add_parameter(Parameter(name="beta_p", expression="0.00266")) + self.add_parameter(Parameter(name="beta_a", expression="0.00094")) + self.add_parameter(Parameter(name="gamma", expression="0.00744")) + self.add_parameter(Parameter(name="zeta", expression="0.2")) + self.add_parameter(Parameter(name="delta", expression="0.1")) + self.add_parameter(Parameter(name="sigma", expression="0.9")) + self.add_parameter(Parameter(name="mu", expression="0.00729")) + self.add_parameter(Parameter(name="mu_prime", expression="0.01159")) + + # Variables + self.add_species(Species(name="Susceptible", initial_value=200, mode="discrete")) + self.add_species(Species(name="Prescribed_User", initial_value=0, mode="discrete")) + self.add_species(Species(name="Addicted", initial_value=0, mode="discrete")) + self.add_species(Species(name="Rehab", initial_value=0, mode="discrete")) + self.add_species(Species(name="Natural_Deaths", initial_value=0, mode="discrete")) + self.add_species(Species(name="Addicted_Deaths", initial_value=0, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="SP", reactants={'Susceptible': 1}, products={'Prescribed_User': 1}, rate=self.listOfParameters["alpha"])) + self.add_reaction(Reaction(name="SA_a", reactants={'Susceptible': 1}, products={'Addicted': 1}, rate=self.listOfParameters["beta_a"])) + self.add_reaction(Reaction(name="SA_p", reactants={'Susceptible': 1}, products={'Addicted': 1}, rate=self.listOfParameters["beta_p"])) + self.add_reaction(Reaction(name="PA", reactants={'Prescribed_User': 1}, products={'Addicted': 1}, rate=self.listOfParameters["gamma"])) + self.add_reaction(Reaction(name="PS", reactants={'Prescribed_User': 1}, products={'Susceptible': 1}, rate=self.listOfParameters["epsilon"])) + self.add_reaction(Reaction(name="AR", reactants={'Addicted': 1}, products={'Rehab': 1}, rate=self.listOfParameters["zeta"])) + self.add_reaction(Reaction(name="RA", reactants={'Rehab': 1}, products={'Addicted': 1}, rate=self.listOfParameters["delta"])) + self.add_reaction(Reaction(name="RS", reactants={'Rehab': 1}, products={'Susceptible': 1}, rate=self.listOfParameters["sigma"])) + self.add_reaction(Reaction(name="mu_S", reactants={'Susceptible': 1}, products={'Susceptible': 1, 'Natural_Deaths': 1}, rate=self.listOfParameters["mu"])) + self.add_reaction(Reaction(name="mu_P", reactants={'Prescribed_User': 1}, products={'Susceptible': 1, 'Natural_Deaths': 1}, rate=self.listOfParameters["mu"])) + self.add_reaction(Reaction(name="mu_R", reactants={'Rehab': 1}, products={'Susceptible': 1, 'Natural_Deaths': 1}, rate=self.listOfParameters["mu"])) + self.add_reaction(Reaction(name="mu_prime_A", reactants={'Addicted': 1}, products={'Susceptible': 1, 'Addicted_Deaths': 1}, rate=self.listOfParameters["mu_prime"])) + + # Timespan + self.timespan(np.arange(0, 200, 1)) + + +class Schlogl(Model): + def __init__(self): + Model.__init__(self, name="Schlogl") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="k1", expression="1")) + self.add_parameter(Parameter(name="k2", expression="1")) + + # Variables + self.add_species(Species(name="s1", initial_value=300, mode="discrete")) + self.add_species(Species(name="s2", initial_value=300, mode="discrete")) + self.add_species(Species(name="s3", initial_value=300, mode="discrete")) + self.add_species(Species(name="s4", initial_value=300, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="r1", reactants={'s1': 1, 's4': 1}, products={'s4': 2}, rate=self.listOfParameters["k1"])) + self.add_reaction(Reaction(name="r2", reactants={'s2': 1, 's4': 1}, products={'s3': 1}, rate=self.listOfParameters["k2"])) + + # Timespan + self.timespan(np.arange(0, 100000, 1000)) + + +class ToggleSwitch(Model): + def __init__(self): + Model.__init__(self, name="Toggle_Switch") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="alpha1", expression="10")) + self.add_parameter(Parameter(name="alpha2", expression="10")) + self.add_parameter(Parameter(name="beta", expression="2")) + self.add_parameter(Parameter(name="gamma", expression="2")) + self.add_parameter(Parameter(name="mu", expression="1")) + + # Variables + self.add_species(Species(name="A", initial_value=2, mode="discrete")) + self.add_species(Species(name="B", initial_value=2, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="cu", reactants={}, products={'A': 1}, propensity_function="alpha1/(1+pow(B, beta))")) + self.add_reaction(Reaction(name="cv", reactants={}, products={'B': 1}, propensity_function="alpha2/(1+pow(A, gamma))")) + self.add_reaction(Reaction(name="du", reactants={'A': 1}, products={}, rate=self.listOfParameters["mu"])) + self.add_reaction(Reaction(name="dv", reactants={'B': 1}, products={}, rate=self.listOfParameters["mu"])) + + # Timespan + self.timespan(np.arange(0, 250, 1)) + + +class VilarOscillator(Model): + def __init__(self): + Model.__init__(self, name="Vilar_Oscillator") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="alpha_a", expression="50")) + self.add_parameter(Parameter(name="alpha_a_prime", expression="500")) + self.add_parameter(Parameter(name="alpha_r", expression="0.01")) + self.add_parameter(Parameter(name="alpha_r_prime", expression="50")) + self.add_parameter(Parameter(name="beta_a", expression="50")) + self.add_parameter(Parameter(name="beta_r", expression="5")) + self.add_parameter(Parameter(name="delta_ma", expression="10")) + self.add_parameter(Parameter(name="delta_mr", expression="0.5")) + self.add_parameter(Parameter(name="delta_a", expression="1")) + self.add_parameter(Parameter(name="delta_r", expression="0.2")) + self.add_parameter(Parameter(name="gamma_a", expression="1")) + self.add_parameter(Parameter(name="gamma_r", expression="1")) + self.add_parameter(Parameter(name="gamma_c", expression="2")) + self.add_parameter(Parameter(name="theta_a", expression="50")) + self.add_parameter(Parameter(name="theta_r", expression="100")) + + # Variables + self.add_species(Species(name="Da", initial_value=1, mode="discrete")) + self.add_species(Species(name="Da_prime", initial_value=0, mode="discrete")) + self.add_species(Species(name="Ma", initial_value=0, mode="discrete")) + self.add_species(Species(name="Dr", initial_value=1, mode="discrete")) + self.add_species(Species(name="Dr_prime", initial_value=0, mode="discrete")) + self.add_species(Species(name="Mr", initial_value=0, mode="discrete")) + self.add_species(Species(name="C", initial_value=10, mode="discrete")) + self.add_species(Species(name="A", initial_value=10, mode="discrete")) + self.add_species(Species(name="R", initial_value=10, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="r1", reactants={'Da_prime': 1}, products={'Da': 1}, rate=self.listOfParameters["theta_a"])) + self.add_reaction(Reaction(name="r2", reactants={'Da': 1, 'A': 1}, products={'Da_prime': 1}, rate=self.listOfParameters["gamma_a"])) + self.add_reaction(Reaction(name="r3", reactants={'Dr_prime': 1}, products={'Dr': 1}, rate=self.listOfParameters["theta_r"])) + self.add_reaction(Reaction(name="r4", reactants={'Dr': 1, 'A': 1}, products={'Dr_prime': 1}, rate=self.listOfParameters["gamma_r"])) + self.add_reaction(Reaction(name="r5", reactants={'Da_prime': 1}, products={'Da_prime': 1, 'Ma': 1}, rate=self.listOfParameters["alpha_a_prime"])) + self.add_reaction(Reaction(name="r6", reactants={'Da': 1}, products={'Da': 1, 'Ma': 1}, rate=self.listOfParameters["alpha_a"])) + self.add_reaction(Reaction(name="r7", reactants={'Ma': 1}, products={}, rate=self.listOfParameters["delta_ma"])) + self.add_reaction(Reaction(name="r8", reactants={'Ma': 1}, products={'A': 1, 'Ma': 1}, rate=self.listOfParameters["beta_a"])) + self.add_reaction(Reaction(name="r9", reactants={'Da_prime': 1}, products={'Da_prime': 1, 'A': 1}, rate=self.listOfParameters["theta_a"])) + self.add_reaction(Reaction(name="r10", reactants={'Dr_prime': 1}, products={'Dr_prime': 1, 'A': 1}, rate=self.listOfParameters["theta_a"])) + self.add_reaction(Reaction(name="r11", reactants={'A': 1}, products={}, rate=self.listOfParameters["gamma_c"])) + self.add_reaction(Reaction(name="r12", reactants={'A': 1, 'R': 1}, products={'C': 1}, rate=self.listOfParameters["gamma_c"])) + self.add_reaction(Reaction(name="r13", reactants={'Dr_prime': 1}, products={'Dr_prime': 1, 'Mr': 1}, rate=self.listOfParameters["alpha_r_prime"])) + self.add_reaction(Reaction(name="r14", reactants={'Dr': 1}, products={'Dr': 1, 'Mr': 1}, rate=self.listOfParameters["alpha_r"])) + self.add_reaction(Reaction(name="r15", reactants={'Mr': 1}, products={}, rate=self.listOfParameters["delta_mr"])) + self.add_reaction(Reaction(name="r16", reactants={'Mr': 1}, products={'Mr': 1, 'R': 1}, rate=self.listOfParameters["beta_r"])) + self.add_reaction(Reaction(name="r17", reactants={'R': 1}, products={}, rate=self.listOfParameters["delta_r"])) + self.add_reaction(Reaction(name="r18", reactants={'C': 1}, products={'R': 1}, rate=self.listOfParameters["delta_a"])) + + # Timespan + self.timespan(np.arange(0, 200, 1)) + + +class Oregonator(Model): + def __init__(self): + Model.__init__(self, name="Oregonator") + self.volume = 1 + + # Parameters + self.add_parameter(Parameter(name="k1", expression="2")) + self.add_parameter(Parameter(name="k2", expression="0.1")) + self.add_parameter(Parameter(name="k3", expression="104")) + self.add_parameter(Parameter(name="k4", expression="4e-07")) + self.add_parameter(Parameter(name="k5", expression="26")) + + # Variables + self.add_species(Species(name="F", initial_value=2, mode="continuous")) + self.add_species(Species(name="A", initial_value=250, mode="continuous")) + self.add_species(Species(name="B", initial_value=500, mode="continuous")) + self.add_species(Species(name="C", initial_value=1000, mode="continuous")) + self.add_species(Species(name="P", initial_value=0, mode="continuous")) + + # Reactions + self.add_reaction(Reaction(name="reaction1", reactants={'B': 1, 'F': 1}, products={'A': 1, 'F': 1}, rate=self.listOfParameters["k1"])) + self.add_reaction(Reaction(name="reaction2", reactants={'A': 1, 'B': 1}, products={'P': 1}, rate=self.listOfParameters["k2"])) + self.add_reaction(Reaction(name="reaction3", reactants={'A': 1, 'F': 1}, products={'A': 2, 'C': 1, 'F': 1}, rate=self.listOfParameters["k3"])) + self.add_reaction(Reaction(name="reaction4", reactants={'A': 2}, products={'P': 1}, rate=self.listOfParameters["k4"])) + self.add_reaction(Reaction(name="reaction5", reactants={'C': 1, 'F': 1}, products={'B': 1, 'F': 1}, rate=self.listOfParameters["k5"])) + + # Timespan + self.timespan(np.arange(0, 5, 0.1)) + + +class TysonOscillator(Model): + def __init__(self): + Model.__init__(self, name="Tyson_Oscillator") + self.volume = 300 + + # Parameters + self.add_parameter(Parameter(name="P", expression="2")) + self.add_parameter(Parameter(name="kt", expression="20")) + self.add_parameter(Parameter(name="kd", expression="1")) + self.add_parameter(Parameter(name="a0", expression="0.005")) + self.add_parameter(Parameter(name="a1", expression="0.05")) + self.add_parameter(Parameter(name="a2", expression="0.1")) + self.add_parameter(Parameter(name="kdx", expression="1")) + + # Variables + self.add_species(Species(name="X", initial_value=197, mode="discrete")) + self.add_species(Species(name="Y", initial_value=255, mode="discrete")) + + # Reactions + self.add_reaction(Reaction(name="rxn1", reactants={}, products={'X': 1}, propensity_function="vol*1/(1+(Y*Y/((vol*vol))))")) + self.add_reaction(Reaction(name="rxn2", reactants={'X': 1}, products={}, rate=self.listOfParameters["kdx"])) + self.add_reaction(Reaction(name="rxn3", reactants={'X': 1}, products={'X': 1, 'Y': 1}, rate=self.listOfParameters["kt"])) + self.add_reaction(Reaction(name="rxn4", reactants={'Y': 1}, products={}, rate=self.listOfParameters["kd"])) + self.add_reaction(Reaction(name="rxn5", reactants={'Y': 1}, products={}, propensity_function="Y/(a0 + a1*(Y/vol)+a2*Y*Y/(vol*vol))")) + + # Timespan + self.timespan(np.arange(0, 100, 1)) diff --git a/stochss/tests/run_tests.py b/stochss/tests/run_tests.py index b7d5d6d5f7..b551054521 100755 --- a/stochss/tests/run_tests.py +++ b/stochss/tests/run_tests.py @@ -37,11 +37,15 @@ import test_model_template import test_settings_template import test_stochss_base + import test_stochss_file + import test_gillespy2 modules = [ test_model_template, test_settings_template, - test_stochss_base + test_gillespy2, + test_stochss_base, + test_stochss_file ] for module in modules: diff --git a/stochss/tests/test_gillespy2.py b/stochss/tests/test_gillespy2.py new file mode 100644 index 0000000000..b16fbfa94a --- /dev/null +++ b/stochss/tests/test_gillespy2.py @@ -0,0 +1,167 @@ +''' +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + +import os +import unittest + +from gillespy2 import GillesPySolver + +from example_models import ( + Brusselator, + Degradation, + Dimerization, + LotkavolterraOscillator, + MichaelisMenten, + Opioid, + Schlogl, + ToggleSwitch, + VilarOscillator, + Oregonator, + TysonOscillator +) + +os.chdir('/stochss') + +# pylint: disable=import-outside-toplevel +class TestGillesPy2Dependency(unittest.TestCase): + ''' + ################################################################################################ + Unit tests for GillesPy2 dependency. + ################################################################################################ + ''' + def setUp(self): + ''' Create a list of common example paths for each test. ''' + self.test_models = [Brusselator, Degradation, Dimerization, LotkavolterraOscillator, + MichaelisMenten, Opioid, Schlogl, ToggleSwitch, VilarOscillator] + + ################################################################################################ + # Unit tests for GillesPy2 dependency check_cpp_support. + ################################################################################################ + + def test_check_cpp_support(self): + ''' Check if the check cpp support functions works in StochSS. ''' + from gillespy2.solvers.utilities.cpp_support_test import check_cpp_support + + self.assertIsInstance(check_cpp_support(), bool) + + ################################################################################################ + # Unit tests for GillesPy2 dependency get_best_solver. + ################################################################################################ + + def test_get_best_solver(self): + ''' Check if the get best solver function works in StochSS. ''' + test_model = self.test_models[0]() + test_solver = test_model.get_best_solver() + self.assertIsInstance(test_solver(), GillesPySolver) + + ################################################################################################ + # Unit tests for GillesPy2 dependency get_best_solver_algo. + ################################################################################################ + + def test_get_best_solver_algo(self): + ''' Check if the get best solver algo function works in StochSS. ''' + test_algos = ["ODE", "SSA", "Tau-Leaping"] + test_model = self.test_models[0]() + for test_algo in test_algos: + with self.subTest(test_algo=test_algo): + test_solver = test_model.get_best_solver_algo(algorithm=test_algo) + self.assertIsInstance(test_solver(), GillesPySolver) + + ################################################################################################ + # Unit tests for GillesPy2 dependency solvers. + ################################################################################################ + + def test_ode_solver(self): + ''' Check if the test_models run with the ODESolver. ''' + from gillespy2 import ODESolver + + self.test_models.append(Oregonator) + for model in self.test_models: + test_model = model() + with self.subTest(model=test_model.name): + test_model.run(solver=ODESolver) + + + def test_ode_c_solver(self): + ''' Check if the test_models run with the ODECSolver. ''' + from gillespy2 import ODECSolver + + self.test_models.append(Oregonator) + for model in self.test_models: + test_model = model() + with self.subTest(model=test_model.name): + test_solver = ODECSolver(model=test_model) + test_model.run(solver=test_solver) + + + def test_numpy_ssa_solver(self): + ''' Check if the test_models run with the NumPySSASolver. ''' + from gillespy2 import NumPySSASolver + + self.test_models.append(TysonOscillator) + for model in self.test_models: + test_model = model() + with self.subTest(model=test_model.name): + test_model.run(solver=NumPySSASolver) + + + def test_ssa_c_solver(self): + ''' Check if the test_models run with the SSACSolver. ''' + from gillespy2 import SSACSolver + + self.test_models.append(TysonOscillator) + for model in self.test_models: + test_model = model() + with self.subTest(model=test_model.name): + test_solver = SSACSolver(model=test_model) + test_model.run(solver=test_solver) + + + def test_tau_leaping_solver(self): + ''' Check if the test_models run with the TauLeapingSolver. ''' + from gillespy2 import TauLeapingSolver + + self.test_models.append(TysonOscillator) + for model in self.test_models: + test_model = model() + with self.subTest(model=test_model.name): + test_model.run(solver=TauLeapingSolver) + + + def test_tau_leaping_c_solver(self): + ''' Check if the test_models run with the TauLeapingCSolver. ''' + from gillespy2 import TauLeapingCSolver + + self.test_models.append(TysonOscillator) + for model in self.test_models: + test_model = model() + with self.subTest(model=test_model.name): + test_solver = TauLeapingCSolver(model=test_model) + test_model.run(solver=test_solver) + + + def test_tau_hybrid_solver(self): + ''' Check if the test_models run with the TauHybridSolver. ''' + from gillespy2 import TauHybridSolver + + self.test_models.append(Oregonator) + self.test_models.append(TysonOscillator) + for model in self.test_models: + test_model = model() + with self.subTest(model=test_model.name): + test_model.run(solver=TauHybridSolver) diff --git a/stochss/tests/test_stochss_base.py b/stochss/tests/test_stochss_base.py index 81c5c979d3..11e2f1f920 100644 --- a/stochss/tests/test_stochss_base.py +++ b/stochss/tests/test_stochss_base.py @@ -33,6 +33,8 @@ os.chdir('/stochss') +# pylint: disable=too-many-public-methods +# pylint: disable=line-too-long class TestStochSSBaseObject(unittest.TestCase): ''' ################################################################################################ diff --git a/stochss/tests/test_stochss_file.py b/stochss/tests/test_stochss_file.py new file mode 100644 index 0000000000..e7d8949be1 --- /dev/null +++ b/stochss/tests/test_stochss_file.py @@ -0,0 +1,270 @@ +''' +StochSS is a platform for simulating biochemical systems +Copyright (C) 2019-2021 StochSS developers. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +''' + +import os +# import json +import shutil +# import logging +import zipfile +import unittest +import tempfile +# import datetime + +from unittest import mock +from pathlib import Path + +from stochss.handlers import StochSSFile +from stochss.handlers.util.stochss_errors import StochSSFileNotFoundError, StochSSUnzipError, \ + StochSSFileExistsError, StochSSPermissionsError + +os.chdir('/stochss') + +# pylint: disable=too-many-public-methods +# pylint: disable=line-too-long +class TestStochSSFileObject(unittest.TestCase): + ''' + ################################################################################################ + Unit tests for the StochSS file class. + ################################################################################################ + ''' + def setUp(self): + ''' Create a temporary directory with a file for each file test. ''' + self.tempdir = tempfile.TemporaryDirectory() + StochSSFile.user_dir = self.tempdir.name + self.test_filepath = os.path.join(self.tempdir.name, "test_file") + Path(self.test_filepath).touch() + + + def tearDown(self): + ''' Cleanup the temp directory after each test. ''' + self.tempdir.cleanup() + StochSSFile.user_dir = os.path.expanduser("~") + + ################################################################################################ + # Unit tests for the StochSS file class __init__ function. + ################################################################################################ + + def test_init__new_file__unique(self): + ''' Check if the new file is written correctly. ''' + StochSSFile(path="test_new_file", new=True) + self.assertIn("test_new_file", os.listdir(self.tempdir.name)) + + + def test_init__new_binary_file__unique(self): + ''' Check if the new binary file is writen correctly. ''' + StochSSFile(path="test_new_file", new=True, body="test body".encode()) + self.assertIn("test_new_file", os.listdir(self.tempdir.name)) + + + def test_init__new_file__not_unique(self): + ''' Check if the new file is writen correctly with a unique name. ''' + StochSSFile(path="test_file", new=True) + self.assertIn("test_file(1)", os.listdir(self.tempdir.name)) + + ################################################################################################ + # Unit tests for the StochSS file class delete function. + ################################################################################################ + + def test_delete(self): + ''' Check if the file is deleted successfully. ''' + test_file = StochSSFile(path=self.test_filepath) + test_resp = test_file.delete() + self.assertNotIn("test_file", os.listdir(self.tempdir.name)) + self.assertIsInstance(test_resp, str) + + + def test_delete__file_not_found_error(self): + ''' Check if the StochSSFileNotFoundError is raised when the target file is missing. ''' + test_file = StochSSFile(path=self.test_filepath) + with mock.patch("os.remove", mock.mock_open()) as mock_remove: + mock_remove.side_effect = FileNotFoundError + with self.assertRaises(StochSSFileNotFoundError): + test_file.delete() + + + def test_delete_permission_error(self): + ''' Check if the StochSSPermissionsError is raised when the user doesn't have the correct permissions. ''' + test_file = StochSSFile(path=self.test_filepath) + with mock.patch("os.remove") as mock_remove: + mock_remove.side_effect = PermissionError + with self.assertRaises(StochSSPermissionsError): + test_file.delete() + + ################################################################################################ + # Unit tests for the StochSS file class duplicate function. + ################################################################################################ + + def test_dulpicate(self): + ''' Check if the file is copied successfully. ''' + test_file = StochSSFile(path=self.test_filepath) + test_resp = test_file.duplicate() + self.assertIn("Message", test_resp.keys()) + self.assertIn("File", test_resp.keys()) + self.assertIn("test_file-copy", os.listdir(self.tempdir.name)) + + + def test_duplicate__model_in_new_format_project(self): + ''' Check if a model in a new format project is copied successfully. ''' + test_proj_path = os.path.join(self.tempdir.name, "test.proj") + test_wkgp_path = os.path.join(test_proj_path, "test.wkgp") + test_model_path = os.path.join(test_wkgp_path, "test.mdl") + os.makedirs(test_wkgp_path) + Path(test_model_path).touch() + test_file = StochSSFile(path=test_model_path) + test_resp = test_file.duplicate() + self.assertIn("Message", test_resp.keys()) + self.assertIn("File", test_resp.keys()) + self.assertIn("test-copy.wkgp", os.listdir(test_proj_path)) + self.assertIn("test-copy.mdl", os.listdir(os.path.join(test_proj_path, "test-copy.wkgp"))) + + + def test_duplicate__file_not_found_error(self): + ''' Check if the StochSSFileNotFoundError is raised when the target file is missing. ''' + test_file = StochSSFile(path=self.test_filepath) + with mock.patch("shutil.copyfile", mock.mock_open()) as mock_copyfile: + mock_copyfile.side_effect = FileNotFoundError + with self.assertRaises(StochSSFileNotFoundError): + test_file.duplicate() + + + def test_duplicate_permission_error(self): + ''' Check if the StochSSPermissionsError is raised when the user doesn't have the correct permissions. ''' + test_file = StochSSFile(path=self.test_filepath) + with mock.patch("shutil.copyfile") as mock_copyfile: + mock_copyfile.side_effect = PermissionError + with self.assertRaises(StochSSPermissionsError): + test_file.duplicate() + + ################################################################################################ + # Unit tests for the StochSS file class move function. + ################################################################################################ + + def test_move(self): + ''' Check if the file is moved successfully. ''' + test_location = os.path.join(self.tempdir.name, "test_location") + test_file_path = os.path.join(test_location, "test_file") + os.mkdir(test_location) + test_file = StochSSFile(path=self.test_filepath) + test_resp = test_file.move(location=test_file_path) + self.assertIsInstance(test_resp, str) + self.assertIn("test_file", os.listdir(test_location)) + + + def test_move__file_not_found_error(self): + ''' Check if the StochSSFileNotFoundError is raised when the target file is missing. ''' + test_file = StochSSFile(path=self.test_filepath) + with mock.patch("os.rename", mock.mock_open()) as mock_rename: + mock_rename.side_effect = FileNotFoundError + with self.assertRaises(StochSSFileNotFoundError): + test_file.move("test_folder") + + + def test_move_permission_error(self): + ''' Check if the StochSSPermissionsError is raised when the user doesn't have the correct permissions. ''' + test_file = StochSSFile(path=self.test_filepath) + with mock.patch("os.rename") as mock_rename: + mock_rename.side_effect = PermissionError + with self.assertRaises(StochSSPermissionsError): + test_file.move("test_folder") + + ################################################################################################ + # Unit tests for the StochSS file class read function. + ################################################################################################ + + def test_read(self): + ''' Check if the file is read successfully. ''' + test_file = StochSSFile(path=self.test_filepath) + with mock.patch("builtins.open", mock.mock_open(read_data="Test Contents"), create=True) as mock_file: + test_data = test_file.read() + mock_file.assert_called_once_with(self.test_filepath, "r") + self.assertEqual(test_data, "Test Contents") + + + def test_read__file_not_found_error(self): + ''' Check if the StochSSFileNotFoundError is raised when the target file is missing. ''' + test_file = StochSSFile(path=self.test_filepath) + with mock.patch("builtins.open", mock.mock_open()) as mock_file: + mock_file.side_effect = FileNotFoundError + with self.assertRaises(StochSSFileNotFoundError): + test_file.read() + + ################################################################################################ + # Unit tests for the StochSS file class unzip function. + ################################################################################################ + + def test_unzip__from_upload_true(self): + ''' Check the return for unzipping an uploaded file. ''' + test_dir_path = os.path.join(self.tempdir.name, "test_folder") + os.mkdir(test_dir_path) + test_file_path = os.path.join(test_dir_path, "test_file") + Path(test_file_path).touch() + test_archive = shutil.make_archive(os.path.join(self.tempdir.name, "test_zip"), "zip", self.tempdir.name, test_dir_path) + shutil.rmtree(test_dir_path) + test_file = StochSSFile(path=test_archive) + test_resp = test_file.unzip() + self.assertIsInstance(test_resp, list) + self.assertFalse(len(test_resp)) + + + def test_unzip__from_upload_false(self): + ''' Check the return for unzipping a file. ''' + test_dir_path = os.path.join(self.tempdir.name, "test_folder") + os.mkdir(test_dir_path) + test_file_path = os.path.join(test_dir_path, "test_file") + Path(test_file_path).touch() + test_archive = shutil.make_archive(os.path.join(self.tempdir.name, "test_zip"), "zip", self.tempdir.name, test_dir_path) + shutil.rmtree(test_dir_path) + test_file = StochSSFile(path=test_archive) + test_resp = test_file.unzip(from_upload=False) + self.assertIsInstance(test_resp, dict) + self.assertIn("message", test_resp.keys()) + + + def test_unzip__file_exists_error(self): + ''' Check if the StochSSFileExistsError is raised when the contents of the archive already exist. ''' + test_dir_path = os.path.join(self.tempdir.name, "test_folder") + os.mkdir(test_dir_path) + test_file_path = os.path.join(test_dir_path, "test_file") + Path(test_file_path).touch() + shutil.make_archive(os.path.join(self.tempdir.name, "test_zip"), "zip", self.tempdir.name, "test_folder") + test_file = StochSSFile(path="test_zip.zip") + with self.assertRaises(StochSSFileExistsError): + test_file.unzip() + + + def test_unzip__bad_zip_file_error__from_upload_true(self): + ''' Check if an error list is returned when the target file cannot be unzipped. ''' + test_file_path = os.path.join(self.tempdir.name, "test_file.zip") + Path(test_file_path).touch() + test_file = StochSSFile(path=test_file_path) + with mock.patch("zipfile.ZipFile.extractall", mock.mock_open()) as mock_extractall: + mock_extractall.side_effect = zipfile.BadZipFile + errors = test_file.unzip() + self.assertIsInstance(errors, list) + self.assertTrue(len(errors) == 1) + + + def test_unzip__bad_zip_file_error__from_upload_false(self): + ''' Check if the StochSSUnzipError is raised when the target file cannot be unzipped. ''' + test_file_path = os.path.join(self.tempdir.name, "test_file.zip") + Path(test_file_path).touch() + test_file = StochSSFile(path=test_file_path) + with mock.patch("zipfile.ZipFile.extractall", mock.mock_open()) as mock_extractall: + mock_extractall.side_effect = zipfile.BadZipFile + with self.assertRaises(StochSSUnzipError): + test_file.unzip(from_upload=False) diff --git a/webpack.hub.config.js b/webpack.hub.config.js index 99119e673d..62330fdbe3 100644 --- a/webpack.hub.config.js +++ b/webpack.hub.config.js @@ -5,6 +5,9 @@ module.exports = { mode: 'development', entry: { home: './client/pages/home.js', + jobPresentation: './client/pages/job-presentation.js', + modelPresentation: './client/pages/model-presentation.js', + notebookPresentation: './client/pages/notebook-presentation.js' }, output: { filename: 'stochss-[name].bundle.js', @@ -18,6 +21,27 @@ module.exports = { template: 'jupyterhub/home_template.pug', name: 'home', inject: false + }), + new HtmlWebpackPlugin({ + title: 'StochSS | Job Presentation', + filename: '../templates/stochss-job-presentation.html', + template: 'jupyterhub/home_template.pug', + name: 'jobPresentation', + inject: false + }), + new HtmlWebpackPlugin({ + title: 'StochSS | Model Presentation', + filename: '../templates/stochss-model-presentation.html', + template: 'jupyterhub/home_template.pug', + name: 'modelPresentation', + inject: false + }), + new HtmlWebpackPlugin({ + title: 'StochSS | Notebook Presentation', + filename: '../templates/stochss-notebook-presentation.html', + template: 'jupyterhub/home_template.pug', + name: 'notebookPresentation', + inject: false }) ], module: {