Serializing / de-serializng DecisionTree - accord.net

I'm using decision trees from Accord.MachineLearning v3.8.0.
Viewing the tree after training in DecisionTreeView works OK. However if I serialise the tree using
Accord.IO.Serializer.Save(tree, fileName);
and then deserialise it with
DecisionTree tree = Accord.IO.Serializer.Load<DecisionTree>(fileName);
and then try to visualise it in DecisionTreeView
decisionTreeView.TreeSource = tree;
I will get
Object reference not set to an instance of an object.
at Accord.MachineLearning.DecisionTrees.DecisionNode.toString(Codification >codebook)
at Accord.MachineLearning.DecisionTrees.DecisionNode.ToString()
at Accord.Controls.DecisionTreeView.convert(DecisionNode node)
at Accord.Controls.DecisionTreeView.convert(DecisionNode node)
at Accord.Controls.DecisionTreeView.update()
at Accord.Controls.DecisionTreeView.set_TreeSource(DecisionTree value)

Found the fix. For some reason, the DecisionNode:s lose the Owner property value in serialising/de-serializing the DecisionTree. Simply after de-seralization, iterate over the DecisionNode:s of the DecisionTree and set the Owner of each DecisionNode to be the DecisionTree itself.

Related

Cannot serialize a string object with Microsoft.Bond

I am using Microsoft.Bond to serialize a class object which works perfectly fine. However, when I try to serialize a simple System.String object, the CompactBinaryWriter writes almost nothing to the output buffer. I am using this code:
string v = "test data";
var outputBuffer = new OutputBuffer();
var writer = new CompactBinaryWriter<OutputBuffer>(outputBuffer);
Serialize.To(writer, v);
var output = outputBuffer.Data;
output in this case is a one element array : {0}, irrespective of the value of v. Can someone point out why this doesn't work?
Bond requires a top-level Bond struct to perform serialization/deserialization.
If only one value needs to be passed/returned, the type bond.Box<T> can be used to quickly wrap a value in a Bond struct. (There's nothing special about bond.Box<T>, except that it ships with Bond.)
Try this:
Serialize.To(writer, Bond.Box.Create(v));
You'll need to deserialize into a bond.Box<string>.
There's an open issue about having better behavior in cases like this.

.NET API array of objects becomes empty object ONLY when returned as JSON

I have a .NET API that was formally rendering views with a model, but is now set to return the model directly to the API caller as a JSON. When rendering the view with the model, I have an array of objects that populates fine. When returning strictly JSON data, it's missing almost all of that data.
Running the debugger, on the return the data is present, but the end result has an empty object instead of an array of objects.
Pseudo Code:
obj.property1 = sqlQuery1.ToArray(); //Empty object if returned using Ok(result)
obj.property2 = sqlQuery2.ToArray(); //Empty object if returned using Ok(result)
obj.property3 = sqlQuery3.ToArray(); //This one comes through for some reason
//Pack these objects into array
return Ok(result); //Most properties become {}, debugging confirms they exist at this point
return View(result); //All properties render normally
It was solved. The issue is that the models were using [DataContract] and this resulting in empty objects. Removing this safely fixed the issue.

How iterate all Property of a node and update the value of each property and save in repository in cq5

My cq5 Content Structure is....
Content
---mywebsite
------base
-----us
--- en
----pageOne
----pageTwo
----pageThree
----pageFour
----cq:content
----par
----pageFourNew
"pageFourNew" has around 500 Properties.
Now I need to get all the properties of "pageFourNew" and to update their value.
For example if I have:
property=prop1
value = prop1 value
I want to do value = value+"some string value append" and save it on the repository.
I want to do this in a programmatically way.
Please share if you have any solution or idea.
You can use PropertyIterator to iterate through all the properties, setProperty() method of node api to set the new value and jcr session to persist the value to get this done. Sample code:
PropertyIterator propertyIterator = pageFourNew.getProperties();
while (propertyIterator.hasNext()) {
Property property = propertyIterator.nextProperty();
pageFourNew.setProperty(property.getName(),
property.getValue().getString() + "");
jcrSession.save();}
You can easily do this as suggested above at JCR level. But as per CQ practices and this blog
It is better practice to operate at Sling level and NOT JCR level, just to avoid overhead of managing the resources. You can use below code which works:
Resource resource = pageFourNew; // assuming you are getting sling resource properly
ModifiableValueMap valueMap = resource.adaptTo(ModifiableValueMap.class);
for(String key : valueMap.keySet()) {
String value = valueMap.get(key, String.class);
value = value + "additional texts";
valueMap.put(key, value);
}
resource.getResourceResolver().commit();
This is cleaner approach.

Access Denied when deleting image file previously used in DataTemplate in WinRT

I have image (PNG) files used by my GridView as part of its DataTemplate. If I try to delete a specific object row in my GridView, I would delete the related image file for that row as well. The images are different for every item on the list.
I'm using this code to delete the image file
StorageFile _file = await DataStore.GetFileAsync(filename);
await _file.DeleteAsync(StorageDeleteOption.Default);
The image file is rendered on the GridView under the GridView's DataTemplate.
So in each object model in my List, I have a public property there that returns an ImageSource for my DataTemplate.
I'm calling my delete procedure right after i deleted the object row from the List and after the GridView has been refreshed of the new List items.
Even though the List does not contain the object (consuming the image) anymore, the app throws the Access is Denied exception if i try to delete the file. While the app is running, if i try to delete that particular file manually (through file explorer), it won't allow me too.
I tried clearing all unused objects in my app, even setting the GridView's ItemSource to null and the List to null before I delete the image. Still the exception persist.
Thanks in advance.
One method you can try is to load the image into a memory steam, then create a BitmapImage object from that stream, you can then set the source of your Image control to that bitmap image.
Since you are not using the actual image file as the source of the image, you can easily delete it anytime :)
Though this is an old question, I have encountered the problem recently in a UWP app and actually managed to find a solution. But first some background information about the problem:
When you create a BitmapImage with a URI, the created URI object holds a reference to the file in your local storage and keeps it open, i.e. non-writable. This btw is only true when the Bitmap is just big enough to fit into the Image entirely, typically small or medium sized Bitmaps. If the Bitmap happens to be big enough, WinRT automatically uses a downsampled version when it is displayed in an Image. In this case the URI does NOT hold a reference to the original file.
Now to the actual solution:
Setting Image.Source to null doesn't do the trick here, as the URI is still alive (until the next GC cycle at least). What DID work for me, was casting the Source to the BitmapImage it originally was and settings the UriSource to null.
var bitmapImage = image.Source as BitmapImage;
if (bitmapImage != null)
bitmapImage.UriSource = null;
And yes, this IS stupid.
Mark already mentioned part of this but there is no need to make it that complicated. Simply, wherever you expect that you need to delete the bitmap while the system is holding it, use a converter like this:
public class SafeImageFileConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
string path = (string)value;
var stream = new MemoryStream(File.ReadAllBytes(path));
return ImageSource.FromStream(() => stream);
}
}
In practice, you might want to check whether the path exists or return an error.png or similar if it doesn't. Also, don't be tempted to use using with the stream, the system will need the stream so you shouldn't dispose it early.
The trick is to use a Uri object to load the image (instead of a string filename) and then to use the EXACT same Uri instance to delete the file (after removing the image from the UI, of course). Here is an example:
//Save the Uri as a member variable so you can get to it later
private Uri uri;
//Create the Uri
uri = new Uri(OriginalImageFilename, UriKind.Absolute);
//Load the image
BitmapImage bitmapImage = new BitmapImage(uri);
//This can also be done by binding a Image control's source property to the uri.
//Delete the image (remember to use the same Uri instance)
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(uri);
await file.DeleteAsync();
As a work-around, i just deleted the unused images during app launch so that no processes are using it. Thanks.

Custom wcf data provider and debugging a relationship error

I'm implementing a custom data provider, I have gotten it to the point that it returns data and can be filtered, but am having some trouble getting relationships to work.
When querying the metadata the relationships look correct, and when querying a table the related property links appear, but when attempting to access a ResourceReference property I get the following exception:
Object reference not set to an instance of an object.
System.NullReferenceException
stacktrace at System.Data.Services.Providers.DataServiceProviderWrapper.GetResourceAssociationSet(ResourceSetWrapper resourceSet, ResourceType resourceType, ResourceProperty resourceProperty)
at System.Data.Services.Providers.DataServiceProviderWrapper.GetContainer(ResourceSetWrapper sourceContainer, ResourceType sourceResourceType, ResourceProperty navigationProperty)
at System.Data.Services.Providers.DataServiceProviderWrapper.GetResourceProperties(ResourceSetWrapper resourceSet, ResourceType resourceType)
at System.Data.Services.Serializers.SyndicationSerializer.WriteObjectProperties(IExpandedResult expanded, Object customObject, ResourceType resourceType, Uri absoluteUri, String relativeUri, SyndicationItem item, DictionaryContent content, EpmSourcePathSegment currentSourceRoot)
at System.Data.Services.Serializers.SyndicationSerializer.WriteEntryElement(IExpandedResult expanded, Object element, ResourceType expectedType, Uri absoluteUri, String relativeUri, SyndicationItem target)
at System.Data.Services.Serializers.SyndicationSerializer.WriteTopLevelElement(IExpandedResult expanded, Object element)
at System.Data.Services.Serializers.Serializer.WriteRequest(IEnumerator queryResults, Boolean hasMoved)
at System.Data.Services.ResponseBodyWriter.Write(Stream stream)
Here's a sample of how I create the relationships:
var sourceReference = new ResourceProperty(
relatedType.ResourceTypeName,
ResourcePropertyKind.ResourceReference,
relatedType.ResourceType);
sourceReference.CanReflectOnInstanceTypeProperty = false;
compoundType.ResourceType.AddProperty(sourceReference);
var destinationReference = new ResourceProperty(
compoundType.ResourceSetName,
ResourcePropertyKind.ResourceSetReference,
compoundType.ResourceType);
destinationReference.CanReflectOnInstanceTypeProperty = false;
source.ResourceType.AddProperty(destinationReference);
var sourceAssociation = new ResourceAssociationSet(
"source",
new ResourceAssociationSetEnd(compoundType.ResourceSet, compoundType.ResourceType, sourceReference),
new ResourceAssociationSetEnd(relatedType.ResourceSet, relatedType.ResourceType, null));
var destinationAssociation = new ResourceAssociationSet(
"destination",
new ResourceAssociationSetEnd(relatedType.ResourceSet, relatedType.ResourceType, destinationReference),
new ResourceAssociationSetEnd(compoundType.ResourceSet, compoundType.ResourceType, null));
From looking at the sample code on the OData website I thought I'd done it all correctly, and cannot determine my error. Any ideas? or tips on debugging a custom WCF Data service?
Update:
Here's what happens just before the null exception.
Have a resource set Collars with a relationship to Projects so I do this query:
blah.svc/Collars(1)/Project
My override of GetResourceAssociationSet in my IDataServiceMetadataProvider gets called with the parameters ResourceSet = Collars, ResourceType = Collar, Property = Project and I return the association set specified above.
GetResourceAssociationSet is then called again with ResourceSet = Projects, ResourceType = Collar, Property = Project and I return the same association set.
Then in System.Data.Services.Providers.GetResourceAssociationSetEnd the variables passed in are resourceSet = Projects, resourceType = Collar, resourceProperty = Project, this function returns null.
Which makes thisEnd in System.Data.Services.Providers.DataServiceProviderWrapper.GetResourceAssociationSet equal to null.
Then GetRelatedResourceAssociationSetEnd is called with the same variables and also returns null.
So it then crashes with the call
ResourceSetWrapper relatedSet = this.ValidateResourceSet(relatedEnd.ResourceSet);
because relatedEnd is null.
Well, in my debugging I noticed the last time GetResourceAssociationSet was called before the error occurred was for a case where the resourceSet and resourceType parameters had different values (in the case of a derived type).
So, I looked and found this
WCF data services (OData), query with inheritance limitation?
...and lo and behold this uninformative null reference exception (at least in my case) is caused by that same issue. I removed the offending property (and then moved it to the base resource set, even though it doesn't exist there in practice), and the issue was resolved.
Interesting side note (in case this helps the original poster): ResourceType.Properties includes properties from Base Types. Had to change some code to use PropertiesDeclaredOnThisType instead...
The solution for me was that I had made a mistake in my implementation of GetResourceType in my IDataServiceQueryProvider.
When querying a Resource Property that was a ResourceSetReference I was returning the ResourceType of the parent resource, and not the type of the related resource.