Weka throws "UnassignedDatasetException" - java

I am working with Weka 3.6.11 and I am having an error which I can't figure out what is causing it.
I have followed pages 202-204 in the Weka manual and have constructed my data like they say. Still when I try t classify the data I get an error.
weka.core.UnassignedDatasetException: Instance doesn't have access to a dataset!
Here is the code I have so far:
public static void classifyTest()
{
try
{
Classifier classifier = (Classifier)weka.core.SerializationHelper.read("iris120.model");
System.Console.WriteLine("----------------------------");
weka.core.Attribute sepallength = new weka.core.Attribute("sepallength");
weka.core.Attribute sepalwidth = new weka.core.Attribute("sepalwidth");
weka.core.Attribute petallength = new weka.core.Attribute("petallength");
weka.core.Attribute petalwidth = new weka.core.Attribute("petalwidth");
FastVector labels = new FastVector();
labels.addElement("Iris-setosa");
labels.addElement("Iris-versicolor");
labels.addElement("Iris-virginica");
weka.core.Attribute cls = new weka.core.Attribute("class", labels);
FastVector attributes = new FastVector();
attributes.addElement(sepallength);
attributes.addElement(sepalwidth);
attributes.addElement(petallength);
attributes.addElement(petalwidth);
attributes.addElement(cls);
Instances dataset = new Instances("TestInstances", attributes, 0);
double[] values = new double[dataset.numAttributes()];
values[0] = 5.0;
values[1] = 3.5;
values[2] = 1.3;
values[3] = 0.3;
Instance inst = new Instance(1,values);
dataset.add(inst);
// Here I try to classify the data that I have constructed.
try
{
double predictedClass = classifier.classifyInstance(inst);
System.Console.WriteLine("Class1: (irisSetosa): " + predictedClass);
}
catch (java.lang.Exception ex)
{
ex.printStackTrace();
}
System.Console.ReadLine();
}
catch (java.lang.Exception ex)
{
ex.printStackTrace();
System.Console.ReadLine();
}
}
From the error message I take it that I need to assign my dataset something but I do not know what or how.
Can someone point out my mistake?
Thanks.

I have found the solution to my own question and thus I am providing the information here so that it might help someone else.
My original problem was that I was getting an "UnsignedDataSetException". To solve that I added a method call to setDataSet like so:
....previous code omitted, can be seen in the question...
Instance inst = new Instance(1.0,values);
dataset.add(inst);
inst.setDataset(dataset);
....following code omitted, can be seen in the question...
After that I got another exception called UnassignedClassException. That means that you have not explicitly set the attribute which is to be used as the outcome of the prediction. Usually it is the last attribute so we add a method called setClassIndex like so:
Instances dataset = new Instances("TestInstances", attributes, 0);
// Assign the prediction attribute to the dataset. This attribute will
// be used to make a prediction.
dataset.setClassIndex(dataset.numAttributes() - 1);
Now it works. It predicts the correct iris (at least for the one I have tried). If something else pops up I will edit this question/answer.
Cheers!

Related

How to automate function according to Array list size

I'm sorry this question header is not 100% correct. Because of that, I'll explain my scenario here.
I created a function to merge 4 data sets into one return format. Because that's the format front-end side needed. So this is working fine now.
public ReturnFormat makeThribleLineChart(List<NameCountModel> totalCount, List<NameCountModel>,p1Count, List<NameCountModel> p2Count, List<NameCountModel> average) {
ReturnFormat returnFormat = new ReturnFormat(null,null);
try {
String[] totalData = new String[totalCount.size()];
String[] p1Data = new String[p1Count.size()];
String[] p2Data = new String[p2Count.size()];
String[] averageData = new String[p2Count.size()];
String[] lableList = new String[totalCount.size()];
for (int x = 0; x < totalCount.size(); x++) {
totalData[x] = totalCount.get(x).getCount();
p1Data[x] = p1Count.get(x).getCount();
p2Data[x] = p2Count.get(x).getCount();
averageData[x] = average.get(x).getCount();
lableList[x] = totalCount.get(x).getName();
}
FormatHelper<String[]> totalFormatHelper= new FormatHelper<String[]>();
totalFormatHelper.setData(totalData);
totalFormatHelper.setType("line");
totalFormatHelper.setLabel("Uudet");
totalFormatHelper.setyAxisID("y-axis-1");
FormatHelper<String[]> p1FormatHelper= new FormatHelper<String[]>();
p1FormatHelper.setData(p1Data);
p1FormatHelper.setType("line");
p1FormatHelper.setLabel("P1 päivystykseen heti");
FormatHelper<String[]> p2FormatHelper= new FormatHelper<String[]>();
p2FormatHelper.setData(p2Data);
p2FormatHelper.setType("line");
p2FormatHelper.setLabel("P2 päivystykseen muttei yöllä");
FormatHelper<String[]> averageFormatHelper= new FormatHelper<String[]>();
averageFormatHelper.setData(averageData);
averageFormatHelper.setType("line");
averageFormatHelper.setLabel("Jonotusaika keskiarvo");
averageFormatHelper.setyAxisID("y-axis-2");
List<FormatHelper<String[]>> formatHelpObj = new ArrayList<FormatHelper<String[]>>();
formatHelpObj.add(totalFormatHelper);
formatHelpObj.add(p1FormatHelper);
formatHelpObj.add(p2FormatHelper);
formatHelpObj.add(averageFormatHelper);
returnFormat.setData(formatHelpObj);
returnFormat.setLabels(lableList);
returnFormat.setMessage(Messages.Success);
returnFormat.setStatus(ReturnFormat.Status.SUCCESS);
} catch (Exception e) {
returnFormat.setData(null);
returnFormat.setMessage(Messages.InternalServerError);
returnFormat.setStatus(ReturnFormat.Status.ERROR);
}
return returnFormat;
}
so, as you can see here, all the formatting is hardcoded. So my question is how to automate this code for list count. Let's assume next time I have to create chart formatting for five datasets. So I have to create another function to it. That's the thing I want to reduce. So I hope you can understand my question.
Thank you.
You're trying to solve the more general problem of composing a result object (in this case ReturnFormat) based on dynamic information. In addition, there's some metadata being setup along with each dataset - the type, label, etc. In the example that you've posted, you've hardcoded the relationship between a dataset and this metadata, but you'd need some way to establish this relationship for data dynamically if you have a variable number of parameters here.
Therefore, you have a couple of options:
Make makeThribleLineChart a varargs method to accept a variable number of parameters representing your data. Now you have the problem of associating metadata with your parameters - best option is probably to wrap the data and metadata together in some new object that is provided as each param of makeThribleLineChart.
So you'll end up with a signature that looks a bit like ReturnFormat makeThribleLineChart(DataMetadataWrapper... allDatasets), where DataMetadataWrapper contains everything required to build one FormatHelper instance.
Use a builder pattern, similar to the collection builders in guava, for example something like so:
class ThribbleLineChartBuilder {
List<FormatHelper<String[]>> formatHelpObj = new ArrayList<>();
ThribbleLineChartBuilder addDataSet(String describeType, String label, String yAxisId, List<NameCountModel> data) {
String[] dataArray = ... ; // build your array of data
FormatHelper<String[]> formatHelper = new FormatHelper<String[]>();
formatHelper.setData(dataArray);
formatHelper.setType(describeType);
... // set any other parameters that the FormatHelper requires here
formatHelpObj.add(formatHelper);
return this;
}
ReturnFormat build() {
ReturnFormat returnFormat = new ReturnFormat(null, null);
returnFormat.setData(this.formatHelpObj);
... // setup any other fields you need in ReturnFormat
return returnFormat;
}
}
// usage:
new ThribbleLineChartBuilder()
.addDataSet("line", "Uudet", "y-axis-1", totalCount)
.addDataSet("line", "P1 päivystykseen heti", null, p1Count)
... // setup your other data sources
.build()

Draw WFS with latlong coordinates to canvas in Java

I am very new to Java programming, I would appreciate any kind of help.
So I want to display a set of lat-long coordinates (more than 50 coordinates) in Java-based canvas (e.g JFrame, Processing) from a WFS server. I have managed to parse lat-long value and print it to the console. Now I'm stuck in how to bring the lat-long coordinates to the screen coordinates (I'd like to draw it on 1000x500 size). I've tried to search for the reference but couldn't find the simplest one for a beginner like me. Here is the current part of my code :
String[] splitc = coord.split(",");
String lon = splitc[0];
String lat = splitc[1];
//parse string to float
float loncoord=Float.parseFloat(lon);
float latcoord=Float.parseFloat(lat);
Can I transfer the coordinates from the WFS to screen coordinates using world2screen.translate of Geotools library as in https://docs.geotools.org/latest/userguide/library/referencing/axis.html ?
In processing, there is a map() function (https://processing.org/reference/map_.html) to transfer from a range to another. I've tried it but it didn't work on my IDE.
One super noob question, I'm trying to store the WFS connection in a function so I can call it in another class, should I store it in static void or use "return"?
If someone can provide an example of a similar task, that would be very helpful. Thanks (Sara)
You can use this formula instead:
float x = ((WIDTH/360.0) * (180 + loncoord));
float y = ((HEIGHT/180.0) * (90 - latcoord));
It should work... Note that it returns a float and takes 5 arguments of the form:
map(input, inputMin, inputMax, outputMin, outputMax)
You only want to create the connection once, so you're left with two viable options: defining the connection as a static variable of a static class, or defining the connection as an instance variable of a class following the singleton pattern.
Assuming you chose the former approach, the method that returns the connection variable should therefore be static but not void:
public static connectionType getConnection() {
return connectionObject;
}
... where connectionType is the datatype of the connection.
The easiest way is to create a GeoTools WFSDataStore, this code builds up the getCapabilities string if the user has given just a URL to the service endpoint and handles authentication if needed. The datastore is stored in a field of the class:
public FetchWFS(String url, String user, String passwd) throws IOException, URISyntaxException {
if (!user.isEmpty()) {
auth = true;
}
baseURL = new URL(url);
List<NameValuePair> nvp = URLEncodedUtils.parse(baseURL.toURI(), "UTF-8");
NameValuePair service = new BasicNameValuePair("service", "wfs");
NameValuePair request = new BasicNameValuePair("request", "getCapabilities");
NameValuePair version = new BasicNameValuePair("version", "2.0.0");
HashMap<String, NameValuePair> parts = new HashMap<>();
parts.put(service.getName(), service);
parts.put(request.getName(), request);
parts.put(version.getName(), version);
for (NameValuePair part : nvp) {
if (part.getName().equalsIgnoreCase("SERVICE")) {
// We don't care what they think this should be
} else if (part.getName().equalsIgnoreCase("REQUEST")) {
// This must be getCapabuilities so we ignore them
} else if (part.getName().equalsIgnoreCase("VERSION")) {
System.out.println("Changing version to " + part.getValue());
parts.put(version.getName(), part);
} else {
parts.put(part.getName(), part);
}
}
URIBuilder builder = new URIBuilder();
builder.setScheme(baseURL.getProtocol());
builder.setHost(baseURL.getHost());
builder.setPort(baseURL.getPort());
builder.setPath(baseURL.getPath());
List<NameValuePair> p = new ArrayList<>();
p.addAll(parts.values());
builder.setParameters(p);
// builder.addParameter("viewparams", "q:\"mySolrQuery\"");
URI uri = builder.build();
System.out.println(uri);
baseURL = uri.toURL();
// fetch the DataStore
Map<String, Object> params = new HashMap<>();
params.put(WFSDataStoreFactory.URL.key, baseURL);
// params.put(WFSDataStoreFactory.WFS_STRATEGY.key, "mapserver");
if (auth) {
params.put(WFSDataStoreFactory.USERNAME.key, user);
params.put(WFSDataStoreFactory.PASSWORD.key, passwd);
}
// params.put(WFSDataStoreFactory.WFS_STRATEGY.key, "mapserver");
datastore = DataStoreFinder.getDataStore(params);
}
Once you have a DataStore (of any type) you can get a list of available
featureTypes and then add one (or more) of them to a map:
JMapFrame frame = new JMapFrame();
MapContent map = new MapContent();
String[] names = datastore.getNames();
featureSource = store.getFeatureSource(names[0]); //fetch first featureType
schema = featureSource.getSchema();
Style style = SLD.createSimpleStyle(schema);
this.layer = new FeatureLayer(featureSource, style);
map.addLayer(layer);
frame.enableToolBar(true);
frame.setMinimumSize(new Dimension(800, 400));
frame.setVisible(true);
The GeoTools Quickstart Tutorial will help you get started with simple mapping, and the Map Styling tutorial will allow you to generate a prettier map when you want more than a simple black and white default map.

Obtaining census block groups from shapefile based on latlong inputs - Java

I am new to shapefile processing. Kindly guide me on how to achieve my below query.
I am using this shapefile tl_2018_us_aiannh.shp from census.gov : TIGER-LINE. I am to obtain the census block group entities like Block, Tract, County subdivision and County details from the shapefile based on the latitude and longitude provided by the user.
My requirement is to achieve this by shapefile alone and not through any API's.
Can someone help on which framework I can achieve this?
What I've tried/using so far:
I have used GeoTools to read the shapefile . Can I continue using the same? Will my requirement be achievable by this tool?
I have gone through a documentation from census.gov which states:
The Census Bureau assigns a code and these appear in fields such as
“TRACTCE”, where “CE” stands for Census. Finally, state-submitted
codes end in “ST”, such as “SLDLST”, and local education agency codes
end in “LEA”, as in “ELSDLEA”.
Which I tried in my code by:
File file = new File("D:\\tl_2018_us_aiannh.shp");
try {
Map<String, String> connect = new HashMap();
connect.put("url", file.toURI().toString());
DataStore dataStore = DataStoreFinder.getDataStore(connect);
String[] typeNames = dataStore.getTypeNames();
String typeName = typeNames[0];
System.out.println("Reading content " + typeName);
SimpleFeatureSource featureSource = dataStore
.getFeatureSource(typeName);
SimpleFeatureCollection collection = featureSource.getFeatures();
SimpleFeatureIterator iterator = collection.features();
try {
while (iterator.hasNext()) {
SimpleFeature feature = iterator.next();
GeometryAttribute sourceGeometry = feature
.getDefaultGeometryProperty();
String name = (String) (feature).getAttribute("TRACTCE");
Property property = feature.getProperty("TRACTCE");
System.out.println(property);
}
} finally {
iterator.close();
}
} catch (Throwable e) {
e.getMessage();
}
But I am receiving null as the value.
Any help would be much helpful.
I have found the solution to this. Hope this would be helpful to someone in need.
SimpleFeature is the type that has the attributes of shape files that you can check when you try to debug or print a line on runtime. You can use the SimpleFeature to get the property. The attributes can be achieved by:
try {
while (iterator.hasNext()) {
SimpleFeature feature = iterator.next();
Property intptlat = feature.getProperty("TRACTCE");
}
}
Make sure you are choosing the Block Groups as the layer type for download in Tiger-Line or which ever site is concerned, where you download the shape file.

How to save and load the object's list to SharedPreferences with/without using Gson?

In my Android app, I used Gson in order to save/load the object's Arraylist in SharedPreferences. Follows are my code using Gson.
public static ArrayList<RequestModal> getModalList(Context ctx) {
Gson gson = new Gson();
String json = getSharedPreferences(ctx).getString("ModalList", new Gson().toJson(new ArrayList<>()));
Type type = new TypeToken<ArrayList<RequestModal>>() {}.getType();
return gson.fromJson(json, type);
}
In here "RequestModal" is the simple object include a bit of strings and integers.
It works well in case "online". But if internet is offline, forever works on below code.
Type type = new TypeToken<ArrayList<RequestModal>>() {}.getType();
How can I solve it? What is the way implement the feature like this with/without using Gson? Please help me anyone having a good idea.
Thank you in advance.
You can implement this without Gson:
public static EpisodeDetails parseEpisodeDetails(String content) {
EpisodeDetails episodeDetails = new EpisodeDetails();
try {
JSONObject jsonObject = new JSONObject(content);
episodeDetails.title = jsonObject.getString("title");
episodeDetails.subTitle = jsonObject.getString("subtitle");
episodeDetails.synopsis = jsonObject.getString("synopsis");
episodeDetails.ends_on = jsonObject.getString("ends_on");
JSONArray images = jsonObject.getJSONArray("image_urls");
if (images.length() > 0) {
episodeDetails.image_url = images.getString(0);
}
} catch (JSONException e) {
e.printStackTrace();
return null;
}
return episodeDetails;
}
What I'm doing is just taking the String, in your case the one saved on the shared prefs called ModalList and inserting the values on my structure, on my code the structure is called EpisodeDetails, on your code the correspondent is RequestModal. If you don't want to do it via code and want to try another library I recommend Jackson.
Another thing, on this line:
String json = getSharedPreferences(ctx).getString("ModalList", new Gson().toJson(new ArrayList<>()));
Your second parameter is not necessary. getString takes the key to load as first parameter and a default value as second paramter (in the case of empty result). You could change this to "" or null.
Well, another solution to your problem could be TinyDB. It makes use of Gson to save ArrayLists of objects in sharedPrefs, its usage is so simple as:
Person person = new Person("john", 24);
tinydb.putObject("user1", person);
ArrayList<Person> usersWhoWon = new ArrayList<Person>();
tinydb.putListObject("allWinners", usersWhoWon);
and that's it, check out my link given above to see the usage details.

NetSuite SOAP API (SuiteTalk) to dump General Ledger

Can anyone give me advice on how to read the general ledger using SuiteTalk, the SOAP API from NetSuite?
For example, if you look at an account or a transaction on the NetSuite UI, there is an option to select "GL Impact". This produces a list of relevant general ledger entries.
However, I couldn't figure out a way to get the same list using SuiteTalk. One initially promising SOAP operation I tried calling was getPostingTransactionSummary(), but that is just a summary and lacks detail such as transaction dates. Another way is to call search() passing a TransactionSearchBasic object. That returns too many types of transaction and I'm not sure which of those actually have an impact on the general ledger.
I'm using Java and Axis toolkit for the SOAP operations, but examples in any language whatsoever (or raw SOAP XML) would be appreciated.
you are on the right track with your transaction search.
You are looking for posting is true and where the line has an account.
However I'd set this up in the saved search editor at least until you've figured out how you are going to filter to manageable numbers of lines. Then use TransactionSearchAdvanced with savedSearchId to pull that info via SuiteTalk
I am able to search GL transaction with below code, this could help you.
public void GetTransactionData()
{
DataTable dtData = new DataTable();
string errorMsg = "";
LoginToService(ref errorMsg);
TransactionSearch objTransSearch = new TransactionSearch();
TransactionSearchBasic objTransSearchBasic = new TransactionSearchBasic();
SearchEnumMultiSelectField semsf = new SearchEnumMultiSelectField();
semsf.#operator = SearchEnumMultiSelectFieldOperator.anyOf;
semsf.operatorSpecified = true;
semsf.searchValue = new string[] { "Journal" };
objTransSearchBasic.type = semsf;
objTransSearchBasic.postingPeriod = new RecordRef() { internalId = "43" };
objTransSearch.basic = objTransSearchBasic;
//Set Search Preferences
SearchPreferences _searchPreferences = new SearchPreferences();
Preferences _prefs = new Preferences();
_serviceInstance.preferences = _prefs;
_serviceInstance.searchPreferences = _searchPreferences;
_searchPreferences.pageSize = 1000;
_searchPreferences.pageSizeSpecified = true;
_searchPreferences.bodyFieldsOnly = false;
//Set Search Preferences
try
{
SearchResult result = _serviceInstance.search(objTransSearch);
List<JournalEntry> lstJEntry = new List<JournalEntry>();
List<JournalEntryLine> lstLineItems = new List<JournalEntryLine>();
if (result.status.isSuccess)
{
for (int i = 0; i <= result.recordList.Length - 1; i += 1)
{
JournalEntry JEntry = (JournalEntry)result.recordList[i];
lstJEntry.Add((JournalEntry)result.recordList[i]);
if (JEntry.lineList != null)
{
foreach (JournalEntryLine line in JEntry.lineList.line)
{
lstLineItems.Add(line);
}
}
}
}
try
{
_serviceInstance.logout();
}
catch (Exception ex)
{
}
}
catch (Exception ex)
{
throw ex;
}
}

Categories