public function xml($parent, $suppliedRegions, &$incompatibilities, $needles = [], $needleUserData = [], $backup = false)
 {
     foreach ($this->results as $result) {
         $resultNode = new DOMNode("result");
         $resultNode->setAttribute('name', $this->result->name);
         $parent->appendChild($resultNode);
     }
     $regions = [];
     $regionsNode = new DOMElement("regions");
     $parent->appendChild($regionsNode);
     foreach ($this->Regions as $region) {
         $entries = $suppliedRegions->filter(function ($r) use($region) {
             return in_array($r->SegmentationType, $region->SegmentationTypes);
         });
         $entries->each(function ($e) {
             $e->Location = strtolower($e->FileId) . '/' . $e->FileName . '.' . $e->Extension;
         });
         $suppliedCount = $entries->count();
         $pivot = $region->pivot;
         if (Config::get('gosmart.check_regions') !== false) {
             if ($pivot->Maximum !== null && $suppliedCount > $pivot->Maximum) {
                 $incompatibilities[] = "Too many region entries for {$region->Name} (max {$pivot->Maximum}, provided {$suppliedCount})";
             }
             if ($pivot->Minimum !== null && $suppliedCount < $pivot->Minimum) {
                 $incompatibilities[] = "Too few region entries for {$region->Name} (min {$pivot->Minimum}, provided {$suppliedCount})";
             }
         } else {
             if ($pivot->Minimum) {
                 for ($k = 0; $k < $pivot->Minimum - $entries->count(); $k++) {
                     $entry = clone $region;
                     $entries[] = $entry;
                     $entry->Location = $region->Name . '.vtp';
                 }
             }
         }
         $k = 0;
         foreach ($entries as $entry) {
             $regionNode = new DOMElement("region");
             $regionsNode->appendChild($regionNode);
             $regionNode->setAttribute('id', $region->Name . '-' . $k);
             $regionNode->setAttribute('name', $region->Name);
             $regionNode->setAttribute('format', $region->Format);
             $regionNode->setAttribute('input', $entry->Location);
             $regionNode->setAttribute('groups', $region->Groups);
             /* groups should be a JSON array */
             $k += 1;
         }
         $suppliedRegions = $suppliedRegions->reject(function ($r) use($region) {
             return $r->SegmentationType == $region->SegmentationType;
         });
     }
     //if (count($suppliedRegions))
     //  $incompatibilities[] = "Unknown regions for model $this->Name : " . implode(', ', $suppliedRegions->lists('Name'));
     $needlesNode = new DOMElement("needles");
     $parent->appendChild($needlesNode);
     $i = 1;
     foreach ($needles as $simulationNeedle) {
         $needle = $simulationNeedle->Needle;
         if ($simulationNeedle->Index) {
             $needleIx = 'needle' . $simulationNeedle->Index;
         } else {
             $needleIx = 'needle' . $i;
         }
         $i += 1;
         $needleNode = new DOMElement("needle");
         $needlesNode->appendChild($needleNode);
         $needleNode->setAttribute("index", $needleIx);
         if ($backup) {
             $needleNode->setAttribute("id", $needle->Id);
             $needleNode->setAttribute("name", $needle->Name);
         }
         /* isset checks value whether NULL */
         if (isset($needleUserData[$needleIx]) && isset($needleUserData[$needleIx]['class'])) {
             $needleNode->setAttribute("class", $needleUserData[$needleIx]['class']);
         } else {
             if (!empty($needle->Class)) {
                 $needleNode->setAttribute("class", $needle->Class);
             } else {
                 $incompatibilities[] = "Needle class is not given for " . $needleIx;
             }
         }
         if (isset($needleUserData[$needleIx]) && isset($needleUserData[$needleIx]['file'])) {
             $needleNode->setAttribute("file", $needleUserData[$needleIx]['file']);
         } else {
             if (!empty($needle->Geometry)) {
                 $needleNode->setAttribute("file", $needle->Geometry);
             } else {
                 $incompatibilities[] = "Needle file is not given for " . $needleIx;
             }
         }
         $parametersNode = new DOMElement("parameters");
         $needleNode->appendChild($parametersNode);
         $tipParameter = Parameter::whereName("NEEDLE_TIP_LOCATION")->first();
         $tipParameter->Value = json_encode($simulationNeedle->Target->asArray);
         $entryParameter = Parameter::whereName("NEEDLE_ENTRY_LOCATION")->first();
         $entryParameter->Value = json_encode($simulationNeedle->Entry->asArray);
         $tipParameter->xml($parametersNode, $backup);
         $entryParameter->xml($parametersNode, $backup);
         $simulationNeedle->Parameters->each(function ($parameter) use($parametersNode, $backup) {
             $parameter->xml($parametersNode, $backup);
         });
     }
     $definition = new DOMElement("definition");
     $definitionText = new DOMText($this->Definition);
     $parent->appendChild($definition);
     $definition->setAttribute('family', $this->Family);
     $definition->appendChild($definitionText);
 }
 /**
  * Run the database seeds.
  *
  * @return void
  */
 public function run()
 {
     Eloquent::unguard();
     $algorithmsXmls = File::allFiles(public_path() . '/algorithms');
     foreach ($algorithmsXmls as $algorithmsXml) {
         $dom = new DomDocument();
         $dom->load($algorithmsXml);
         $root = $dom->documentElement;
         $modality = Modality::whereName($root->getAttribute('modality'))->first();
         if (empty($modality)) {
             throw new Exception("Could not find modality! ({$algorithmsXml})");
         }
         $protocolName = $root->getAttribute('protocol');
         $protocol = Protocol::whereName($protocolName)->whereModalityId($modality->Id)->first();
         if (empty($protocol)) {
             \Log::warning("Could not find protocol! ({$algorithmsXml})");
             continue;
         }
         $arguments = [];
         $parameters = [];
         $description = "";
         foreach ($root->childNodes as $node) {
             if (get_class($node) == 'DOMText') {
                 continue;
             }
             switch ($node->nodeName) {
                 case 'arguments':
                     foreach ($node->childNodes as $argument) {
                         if (get_class($argument) == 'DOMText') {
                             continue;
                         }
                         $arguments[] = ['Name' => $argument->getAttribute('name')];
                     }
                     break;
                 case 'parameters':
                     foreach ($node->childNodes as $parameter) {
                         if (get_class($parameter) == 'DOMText') {
                             continue;
                         }
                         $parameters[] = ['Name' => $parameter->getAttribute('name'), 'Type' => $parameter->getAttribute('type'), 'Value' => $parameter->hasAttribute('value') ? $parameter->getAttribute('value') : null];
                     }
                     break;
                 case 'description':
                     $description = $node->textContent;
                     break;
                 default:
                     throw new Exception("Unrecognized entry in algorithm XML - {$node->nodeName}! ({$algorithmsXml})");
             }
         }
         $algorithm = new Algorithm();
         $algorithm->content = $description;
         $resultName = $root->getAttribute('result');
         $resultType = $root->getAttribute('type');
         $result = Parameter::whereName($resultName)->first();
         if (empty($result)) {
             $result = Parameter::create(['Name' => $resultName, 'Type' => $resultType]);
         }
         $algorithm->result()->associate($result);
         $algorithm->protocol()->associate($protocol);
         $algorithm->save();
         foreach ($arguments as $argument) {
             $algorithm->arguments()->attach(Argument::create($argument));
         }
         foreach ($parameters as $parameter) {
             $algorithm->attribute($parameter);
         }
     }
 }
 public static function fromXml($xml)
 {
     $xpath = new DOMXpath($xml);
     $simulation = new static();
     $simulationNode = $xpath->query('//simulationDefinition/simulation')->item(0);
     $simulation->Id = strtoupper($simulationNode->getAttribute('id'));
     $simulationAttributes = ['Caption', 'SegmentationType', 'Progress', 'State', 'Color', 'Active'];
     foreach ($simulationAttributes as $simulationAttribute) {
         $simulation->{$simulationAttribute} = $simulationNode->getAttribute(strtolower($simulationAttribute));
     }
     //if (Simulation::find($simulation->Id))
     //  return [false, "Simulation with this ID already exists"];
     $simulationNeedle = [];
     $combination = Combination::find($xpath->query('//simulationDefinition/combination/@id')->item(0)->value);
     if (!$combination) {
         throw new Exception("Cannot find combination (you may be able to work around this manually from the XML)");
     }
     $patient = DB::table('ItemSet_Patient')->where('Id', '=', $xpath->query('//simulationDefinition/simulation/patient/@id')->item(0)->value)->get();
     if (empty($patient)) {
         throw new Exception("Patient no longer exists");
     }
     $patient = $patient[0];
     $simulation->Combination_Id = $combination->Combination_Id;
     $simulation->Patient_Id = $patient->Id;
     $simulation->Id = null;
     $simulation->save();
     $parameterNodes = $xpath->query('//simulationDefinition/parameters/parameter');
     $parameters = [];
     foreach ($parameterNodes as $parameterNode) {
         $parameter = Parameter::whereName($parameterNode->getAttribute("name"))->first();
         $simulation->Parameters()->attach($parameter, ["ValueSet" => $parameterNode->getAttribute("value")]);
     }
     $needleNodes = $xpath->query('//simulationDefinition/numericalModel/needles/needle');
     foreach ($needleNodes as $needleNode) {
         $needle = Needle::find($needleNode->getAttribute("id"));
         if (!$needle) {
             throw new Exception("Needle not found");
         }
         $simulationNeedle = new SimulationNeedle();
         $simulationNeedle->Needle_Id = $needle->Id;
         $simulationNeedle->Simulation_Id = $simulation->Id;
         $simulationNeedle->save();
         $parameterNodes = $xpath->query('//simulationDefinition/numericalModel/needles/needle/parameters/parameter');
         $parameters = [];
         foreach ($parameterNodes as $parameterNode) {
             $parameter = Parameter::whereName($parameterNode->getAttribute("name"))->first();
             switch ($parameter->Name) {
                 case "NEEDLE_TIP_LOCATION":
                     $target = PointSet::fromArray(json_decode($parameterNode->getAttribute("value")));
                     $target->save();
                     $simulationNeedle->Target_Id = $target->Id;
                     break;
                 case "NEEDLE_ENTRY_LOCATION":
                     $entry = PointSet::fromArray(json_decode($parameterNode->getAttribute("value")));
                     $entry->save();
                     $simulationNeedle->Entry_Id = $entry->Id;
                     break;
                 default:
                     $simulationNeedle->Parameters()->attach($parameter, ["ValueSet" => $parameterNode->getAttribute("value")]);
             }
         }
         $simulationNeedle->save();
     }
     //foreach ($parameters as $sP)
     //{
     //  $sP->Simulation_Id = $simulation->Id;
     //  $sP->save();
     //}
     $simulation->save();
     return $simulation;
 }
 public function makeSimulation($caption, $patient, $organ, $model, $protocol, $parameterData, $regionData, $needles)
 {
     $numerical_model = NumericalModel::whereName($model)->first();
     $protocol = Protocol::whereName($protocol)->whereModalityId($numerical_model->Modality_Id)->first();
     $context = Context::byNameFamily($organ, 'organ');
     $combinations = $numerical_model->Combinations()->whereProtocolId($protocol->Id)->where(Context::$idField, "=", $context->Id);
     $combination = $combinations->first();
     $simulation = Simulation::create(['Combination_Id' => $combination->Combination_Id, 'Patient_Id' => $patient->Id ?: '00000000-0000-0000-0000-000000000000', 'Caption' => 'Sample Simulation for ' . $caption, 'SegmentationType' => 0, 'Progress' => '0', 'State' => 0, 'Color' => 0, 'Active' => 0]);
     /*
         foreach ($regionData as $name => $locations)
         {
      $region = Region::whereName($name)->first();
      foreach ($locations as $location)
        $simulation->regions()->attach($region, ['Location' => $location]);
         }
     */
     $simulation->save();
     $simulationNeedles = [];
     $needleData = [];
     $needleUserParameters = new Collection();
     $n = 0;
     foreach ($needles as $needleConfig) {
         $n++;
         $needle = Needle::whereManufacturer($needleConfig["Manufacturer"])->whereName($needleConfig["Name"])->first();
         $needleUserParameters[$needle->Id] = new Collection();
         $simulationNeedle = SimulationNeedle::create(['Needle_Id' => $needle->Id, 'Simulation_Id' => $simulation->Id, 'Target_Id' => $this->makePointSet($needleConfig["Parameters"]["NEEDLE_TIP_LOCATION"])->Id, 'Entry_Id' => $this->makePointSet($needleConfig["Parameters"]["NEEDLE_ENTRY_LOCATION"])->Id]);
         $simulationNeedleId = $simulationNeedle->Id;
         foreach ($needleConfig["Parameters"] as $paramName => $paramValue) {
             $parameter = Parameter::whereName($paramName)->first();
             $parameter->Value = $paramValue;
             $needleUserParameters[$needle->Id][$paramName] = $parameter;
         }
         $simulationNeedles[] = $needle;
     }
     $parameters = new Collection();
     foreach ($parameterData as $parameterName => $value) {
         $parameter = Parameter::whereName($parameterName)->first();
         $parameter->Value = $value;
         $parameters[$parameter->Name] = $parameter;
     }
     $incompatibilities = [];
     $userRequiredParameters = [];
     list($parameters, $needleParameters) = $combination->compileParameters($parameters, $simulationNeedles, $needleUserParameters, $incompatibilities, $userRequiredParameters);
     if (count($incompatibilities)) {
         var_dump($incompatibilities);
         var_dump($userRequiredParameters);
     }
     foreach ($parameters as $parameterName => $parameter) {
         $simulation->Parameters()->attach($parameter, ['ValueSet' => $parameter->Value]);
     }
     $simulation->SimulationNeedles->each(function ($simulationNeedle) use($needleParameters) {
         if (array_key_exists($simulationNeedle->Needle_Id, $needleParameters)) {
             $needleParameters[$simulationNeedle->Needle_Id]->each(function ($p) use($simulationNeedle) {
                 $simulationNeedle->Parameters()->attach($p);
             });
         }
     });
     $this->r++;
     print "Simulation #{$this->r}: " . $simulation->Combination->asString . " [ " . strtoupper($simulation->Id) . " ]\n";
 }
 /**
  * Update the specified resource in storage.
  *
  * @param  int  $id
  * @return Response
  */
 public function update($id)
 {
     $simulation = Simulation::find($id);
     if (Input::has('caption')) {
         $simulation->Caption = Input::get('caption');
     }
     $simulation->save();
     if (Input::has('Combination_Id')) {
         $simulation->Combination_Id = Input::get('Combination_Id');
         $simulation->save();
         $this->rebuild($simulation->Id);
     }
     foreach ($simulation->Parameters as $parameter) {
         if (Input::has('parameters-' . $parameter->Id)) {
             $parameter->pivot->ValueSet = Input::get('parameters-' . $parameter->Id);
             $parameter->pivot->save();
         }
     }
     if (Input::get('new-parameter-name') && Input::get('new-parameter-value') != '') {
         $parameter = Parameter::whereName(Input::get('new-parameter-name'))->first();
         if ($parameter) {
             $simulation->Parameters()->attach($parameter, ["ValueSet" => Input::get('new-parameter-value')]);
             $simulation->save();
         }
     }
     foreach ($simulation->SimulationNeedles as $simulationNeedle) {
         foreach ($simulationNeedle->Parameters as $parameter) {
             if (Input::has('needle-parameters-' . $simulationNeedle->Id . '-' . $parameter->Id)) {
                 $parameter->pivot->ValueSet = Input::get('needle-parameters-' . $simulationNeedle->Id . '-' . $parameter->Id);
                 $parameter->pivot->save();
             }
         }
         $newparameterprefix = 'needle-' . $simulationNeedle->Id . '-new-parameter-';
         if (Input::get($newparameterprefix . 'name') && Input::get($newparameterprefix . 'value') != '') {
             $parameter = Parameter::whereName(Input::get($newparameterprefix . 'name'))->first();
             if ($parameter) {
                 $simulationNeedle->Parameters()->attach($parameter, ["ValueSet" => Input::get($newparameterprefix . 'value')]);
                 $simulationNeedle->save();
             }
         }
     }
     if (Input::get('removing')) {
         if (Input::get('simulation-needle-id')) {
             $simulationNeedle = SimulationNeedle::find(Input::get('simulation-needle-id'));
             $simulationNeedle->delete();
         }
         if (Input::get('region-remove-id')) {
             $region = Region::find(Input::get('region-remove-id'));
             if (Input::get('region-remove-location')) {
                 $simulation->Regions()->newPivotStatementForId($region->Id)->where('Location', '=', Input::get('region-remove-location'))->delete();
             } else {
                 $simulation->Regions()->newPivotStatementForId($region->Id)->whereNull('Location')->delete();
             }
         }
     } else {
         if (Input::get('needle-id')) {
             $needle = Needle::find(Input::get('needle-id'));
             $simulationNeedle = new SimulationNeedle();
             $simulationNeedle->Simulation_Id = $simulation->Id;
             $simulationNeedle->Needle_Id = $needle->Id;
             $target = json_decode(Input::get('needle-target'));
             $simulationNeedle->Target_Id = PointSet::create(['X' => $target[0], 'Y' => $target[1], 'Z' => $target[2]])->Id;
             $entry = json_decode(Input::get('needle-entry'));
             $simulationNeedle->Entry_Id = PointSet::create(['X' => $entry[0], 'Y' => $entry[1], 'Z' => $entry[2]])->Id;
             $simulationNeedle->save();
         }
         if (Input::get('region-id')) {
             $region = Region::find(Input::get('region-id'));
             $simulation->Regions()->attach($region, ['Location' => Input::get('region-location')]);
             $simulation->save();
         }
     }
     return Redirect::route('simulation.edit', $id);
 }
 public function attribute($data, $context = null, $overwrite = true, $overwrite_parameter = false)
 {
     $name = $data['Name'];
     if (!$this->Id) {
         throw new InvalidArgumentException("Cowardly refusing to create an empty (universal) attribute");
     }
     /* Convention over configuration */
     $id_name = train_case(get_class($this)) . '_Id';
     if ($id_name == 'Context_Id') {
         $id_name = Context::$idField;
     }
     $parameterClause = ParameterAttribution::where($id_name, '=', $this->Id);
     $activeFields = [snake_case(get_class($this))];
     if ($context !== null) {
         $activeFields[] = 'context';
         $parameterClause = $parameterClause->where(Context::$idContext, '=', $context->Id);
     }
     $parameterAttributions = $parameterClause->whereHas('parameter', function ($q) use($name) {
         $q->where('Name', '=', $name);
     })->get()->filter(function ($pa) use($activeFields) {
         return empty(array_diff(array_values($pa->activeFields()), array_values($activeFields)));
     });
     $parameterAttribution = $parameterAttributions->first();
     $parameterAttributions->each(function ($pa) {
         $pa->delete();
     });
     if (array_key_exists('Value', $data)) {
         $value = $data['Value'];
         unset($data['Value']);
     } else {
         $value = null;
     }
     if (array_key_exists('Widget', $data)) {
         $widget = $data['Widget'];
         unset($data['Widget']);
     } else {
         $widget = null;
     }
     if (array_key_exists('Units', $data)) {
         $units = $data['Units'];
         unset($data['Units']);
     } else {
         $units = null;
     }
     if (array_key_exists('Editable', $data)) {
         $editable = $data['Editable'];
         unset($data['Editable']);
     } else {
         $editable = 2;
     }
     if ($parameterAttribution) {
         $parameter = $parameterAttribution->parameter;
         if ($overwrite) {
             $parameterAttribution->Value = $value;
             $parameterAttribution->Editable = $editable;
             $parameterAttribution->Widget = $widget;
             $parameterAttribution->Units = $units;
             $parameterAttribution->save();
         } else {
             $value = $parameterAttribution->Value;
             $editable = $parameterAttribution->Editable;
             $widget = $parameterAttribution->Widget;
             $units = $parameterAttribution->Units;
         }
     } else {
         $parameter = Parameter::whereName($data['Name'])->first();
         if (empty($parameter)) {
             $parameter = Parameter::create($data);
         } else {
             $parameter->update(array_filter($data));
         }
         /* Convention over configuration */
         $id_name = train_case(get_class($this)) . '_Id';
         if ($id_name == 'Context_Id') {
             $id_name = Context::$idField;
         }
         $type = array_key_exists('Type', $data) ? $data['Type'] : $parameter->Type;
         $widget = isset($widget) ? $widget : $parameter->Widget;
         $units = isset($units) ? $units : $parameter->Units;
         $attribution = [$id_name => $this->Id, 'Parameter_Id' => $parameter->Id, 'Value' => $value, 'Format' => $type, 'Editable' => $editable, 'Widget' => $widget, 'Units' => $units];
         if ($context !== null) {
             $attribution[Context::$idContext] = $context->Id;
         }
         $parameterAttribution = ParameterAttribution::create($attribution);
     }
     if ($parameter->Widget === null && $parameter->Units === null || $overwrite_parameter) {
         $parameter->Widget = $widget;
         $parameter->Units = $units;
     }
     $parameter->Value = $value;
     $parameter->Editable = $editable;
     $parameter->Widget = $widget;
     $parameter->Units = $units;
     $parameterAttribution->save();
     return $parameter;
 }
 /**
  * Run the database seeds.
  *
  * @return void
  */
 public function run()
 {
     Eloquent::unguard();
     $parameterFields = ['name', 'type', 'widget', 'description', 'units', 'priority', 'restriction'];
     $attributionFields = ['Name', 'Type', 'Widget', 'Units'];
     $constantsXmls = File::allFiles(public_path() . '/constants');
     foreach ($constantsXmls as $constantsXml) {
         $dom = new DomDocument();
         $dom->load($constantsXml);
         $root = $dom->documentElement;
         $class = $root->getAttribute('class');
         $name = $root->getAttribute('name');
         //FIXME: Not very safe!
         if (Config::get('gosmart.context_as_enum') && $class == 'Context') {
             if ($root->hasAttribute('family')) {
                 $family = $root->getAttribute('family');
             } else {
                 $family = 'organ';
             }
             $target = Context::byNameFamily($name, $family);
         } else {
             $object = new $class();
             $objectQuery = $object->whereName($name);
             if ($root->hasAttribute('family')) {
                 $objectQuery = $objectQuery->whereFamily($root->getAttribute('family'));
             }
             $target = $objectQuery->first();
         }
         if (empty($target)) {
             throw new Exception("Did not find object {$name} ({$class}) for {$constantsXml}");
         }
         foreach ($root->childNodes as $constant) {
             if (get_class($constant) == 'DOMText') {
                 continue;
             }
             if (!$constant->hasAttribute('name')) {
                 throw new Exception("Constant missing name! ({$constantsXml})");
             }
             $present = array_filter($parameterFields, [$constant, 'hasAttribute']);
             $parameterData = [];
             array_map(function ($a) use(&$parameterData, $constant) {
                 $parameterData[train_case($a)] = $constant->getAttribute($a);
             }, $present);
             if (!$constant->hasAttribute('description')) {
                 $parameterData['Description'] = $parameterData['Name'];
             }
             $parameterData['Name'] = preg_replace('/[ -]/', '_', $parameterData['Name']);
             $parameterData['Name'] = strtoupper($constant->nodeName) . '_' . strtoupper(preg_replace('/[[:^word:]]/', '', $parameterData['Name']));
             if (!$constant->hasAttribute('type')) {
                 $parameterData['Type'] = 'float';
             }
             $parameter = Parameter::whereName($parameterData['Name'])->first();
             if (empty($parameter)) {
                 $parameter = Parameter::create($parameterData);
             } else {
                 $parameter->fill($parameterData)->save();
             }
             $id_name = train_case($class) . '_Id';
             if ($id_name == "Context_Id") {
                 $id_name = Context::$idField;
             }
             $attributionData = array_intersect_key($parameterData, array_flip($attributionFields));
             if ($constant->hasAttribute('context')) {
                 //$attributionData[Context::$idField] = Context::byNameFamily($constant->getAttribute('context'), $constant->getAttribute('contextFamily') ?: 'organ')->first()->id;
                 $context = Context::byNameFamily($constant->getAttribute('context'), $constant->getAttribute('contextFamily') ?: 'organ')->first();
             } else {
                 $context = null;
             }
             if ($constant->hasAttribute('value')) {
                 $attributionData['Value'] = $constant->getAttribute('value');
             } else {
                 $attributionData['Value'] = null;
             }
             $attribution = $target->attribute($attributionData, $context);
         }
     }
 }