-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GeoDataFrame init #909
base: master
Are you sure you want to change the base?
GeoDataFrame init #909
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good initial version :) just some comments here and there
implementation(libs.ktor.serialization.kotlinx.json) | ||
|
||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it still required to be a friend module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, need some internal stuff for integration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only for the jupyter integration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
import org.jetbrains.kotlinx.dataframe.api.with | ||
|
||
class GeoDataFrame<T : GeoFrame>(val df: DataFrame<T>, val crs: CoordinateReferenceSystem?) { | ||
fun update(updateBlock: DataFrame<T>.() -> DataFrame<T>): GeoDataFrame<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you consider other names? Like
updateDf
replaceDf
(more consistent with what replace does in DF compared to update)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replace
implies that we have df1 and df2, and we change df1 to df2. But in reality we are only modifying df1 slightly, using it as a receiver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, what do you think about modifyDf
then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion "Df" is redundant and doesn't look good. Plus it's already clear from signature that it applies to DataFrame
return GeoDataFrame(df.updateBlock(), crs) | ||
} | ||
|
||
fun applyCRS(targetCRS: CoordinateReferenceSystem? = null): GeoDataFrame<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proper camel casing would be "applyCrs" and "targetCrs"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
with(libs.plugins) { | ||
alias(kotlin.jvm) | ||
alias(publisher) | ||
alias(jupyter.api) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you include ktlint too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, but comment it because it adds too many linting warnings
|
||
object Geocoder { | ||
|
||
private val url = "https://geo2.datalore.jetbrains.com/map_data/geocoding" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be included in the stock library? As far as I remember this was a reverse engineering endeavour and since it depends on an external URL behaviour might change or stop working entirely
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this experimental module, I am totally fine with including in library.
- It's stable for enough time
- We not guarantee for a while all our releases of experimental geo-module
But we could also include this solution for the @Jolanrensen question:
- Checking the API availability and handling the unavailability with some exception
- Checking the API consistency and notification for the users or raise an exception
- Customize it with a URL parameter (if this API just will be moved in another place)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it true, that the main problem was that we could not add fileds by some reason to the descendants of the DataFrame? @Jolanrensen @koperagen
@@ -41,3 +41,4 @@ plugins { | |||
} | |||
include("dataframe-excel") | |||
include("core") | |||
include("dataframe-geo") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you want dataframe-geo to be imported by default when users depend on the generic dataframe package, also add dataframe-geo in build.gradle.kts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I'd like to be it separated
return execute(codeWithConverter, variableName) | ||
} | ||
|
||
override fun Builder.onLoaded() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does this jupyter integration do exactly? could you add some docs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, ok, but there's no docs for core integration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a test like below will make things clearer
for reference:
org.jetbrains.kotlinx.dataframe.jupyter.DataFrameJupyterTest and org.jetbrains.kotlinx.dataframe.jupyter.CodeGenerationTests
test:
val geo = **create geo**
val updatedGeo = geo.update { add("col") { 1 } }
updatedGeo.df.col
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, ok, but there's no docs for core integration
That's not a good argument haha. We also need kdocs there :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
import java.net.URL | ||
|
||
|
||
fun GeoDataFrame.Companion.readGeoJSON(path: String): GeoDataFrame<*> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
readGeoJson is proper camel casing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, but geotools use GeoJSON
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
typeBuilder.name = name ?: "geodata" | ||
typeBuilder.setCRS(crs) | ||
val geometryClass = if (singleGeometryType) { | ||
// todo singleOrNull() ?: error() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
many todo's haha
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it's ok since it's very alpha.
import org.jetbrains.kotlinx.dataframe.geo.GeoFrame | ||
import org.locationtech.jts.geom.Geometry | ||
|
||
fun SimpleFeatureCollection.toGeoDataFrame(): GeoDataFrame<*> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please rename the file to "toGeoDataFrame" like you did with the other file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, I am approving these changes, but want to summarize some thoughts and make this piece of code more mature and maintanable
repositories { | ||
// geo repositories should come before Maven Central | ||
maven("https://maven.geotoolkit.org") | ||
maven("https://repo.osgeo.org/repository/release") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it true, that these maven repo links will be hidden in the module, and the final user don't need to refer to them somehow in its Gradle script? (just for self checking)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, the user will need to add the repository. However, I believe we can fix this with shadow jar.
useJUnitPlatform() | ||
} | ||
kotlin { | ||
jvmToolchain(11) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we downgrade it somehow to 8?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a global problem - DataFrame uses 8 and the Jupyter API uses 11. Therefore, in the future it will be necessary to allocate separate module(s) for integrations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but for now, for convenience, I'd keep it 11
import kotlin.reflect.full.isSubtypeOf | ||
import kotlin.reflect.typeOf | ||
|
||
internal class IntegrationGeo : JupyterIntegration() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's define the final scope of this integration: what we want to achieve with that? Please add an explanation for this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
import org.locationtech.jts.geom.Polygon | ||
|
||
@DataSchema | ||
interface GeoFrame { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name is lead in the wrong direction. It's not GeoFrame. It's close to wrappers for Geometry or Form or GeometryForm
I agree, that geometry is produced from Geo, but it's misleading me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we have Geometry from jts, what do you think about Form or Figure or GeometryFigure/GeometryType or GeometryColumnType, verbose but clear
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WithGeometry
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
object Geocoder { | ||
|
||
private val url = "https://geo2.datalore.jetbrains.com/map_data/geocoding" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this experimental module, I am totally fine with including in library.
- It's stable for enough time
- We not guarantee for a while all our releases of experimental geo-module
But we could also include this solution for the @Jolanrensen question:
- Checking the API availability and handling the unavailability with some exception
- Checking the API consistency and notification for the users or raise an exception
- Customize it with a URL parameter (if this API just will be moved in another place)
|
||
object Geocoder { | ||
|
||
private val url = "https://geo2.datalore.jetbrains.com/map_data/geocoding" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it true, that the main problem was that we could not add fileds by some reason to the descendants of the DataFrame? @Jolanrensen @koperagen
import org.locationtech.jts.geom.Geometry | ||
import org.locationtech.jts.geom.util.AffineTransformation | ||
|
||
fun Geometry.scale(value: Double): Geometry { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return transformation.transform(this) | ||
} | ||
|
||
fun Geometry.translate(valueX: Double, valueY: Double): Geometry { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you consider renaming to somthing like shift/move for simplicity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "translate" is a common name in the math/geometry-world
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the main issue, that we are doing this not for math guys, but for Kotlin developers who are not familiar with all these concepts, and I am trying to make the naming simpler and more obvious
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a well-established concept, so I can't agree:
https://en.wikipedia.org/wiki/Translation_(geometry)
} | ||
|
||
companion object { | ||
val DEFAULT_CRS = CRS.decode("EPSG:4326", true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be ENUM of different constants
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it even exists in some form in GeoTools (see DefaultEngineeringCRS). But here is a more global question - whether it is necessary to use geotools API directly or should we wrap it completely.
|
||
fun GeoDataFrame<*>.writeGeoJson(path: String): Unit = writeGeoJson(File(path)) | ||
|
||
fun GeoDataFrame<*>.writeGeoJson(file: File) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add for IO part some JUnit tests for reading/writing files close to your examples https://gist.github.com/AndreiKingsley/8eada06f174c681e953f8d939248d153
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
No description provided.